diff --git a/docs/ERRORS.md b/docs/ERRORS.md index 898362b55..4cb6059a9 100644 --- a/docs/ERRORS.md +++ b/docs/ERRORS.md @@ -6,7 +6,6 @@ - [Access control error_handler](#access-control-error_handler) - [Scope related error_handler](#scope-related-error_handler) - [Endpoint related error_handler](#endpoint-related-error_handler) - - [error_handler specification](#error_handler-specification) - [Error types](#error-types) - [Access control error types](#access-control-error-types) - [API/endpoint error types](#api-and-endpoint-error-types) @@ -25,38 +24,18 @@ Detailed information is provided via log message. This way, all information can ## Access control `error_handler` Access control errors in particular require special handling, e.g. sending a specific response for missing login credentials. -For this purpose every access control definition of `basic_auth`, `jwt` or `saml2` can define one or multiple `error_handler` with one or more defined error type labels listed below. +For this purpose every access control definition of `basic_auth`, `jwt` or `saml2` can define one or multiple [`error_handler` blocks](REFERENCE.md#error-handler-block) with one or more defined error type labels listed below. ## Scope related `error_handler` Since an [AC](#access-control-error_handler) error handler is rather general than scopes handled per endpoint or http-method but are still protected with the -same access-control. Reacting to those more path specific errors you can define one or more `error_handler` blocks within +same access-control. Reacting to those more path specific errors you can define one or more [`error_handler` blocks](REFERENCE.md#error-handler-block) within an `api` or `endpoint` block. ## Endpoint related `error_handler` A [sequence](REFERENCE.md#endpoint-sequence), a simple `request` or `proxy` error can be handled in combination with the `expected_status` attribute for `request` -and `proxy` block definitions and an `error_handler` definition with the [related](#endpoint-error-types) type label. - -## `error_handler` specification - -The error handler label specifies which [error type](#error-types) -should be handled. Multiple labels are allowed. The label can be omitted to catch all errors which are related to this access control definition. This has the same behavior as the error type `*`, that catches all errors explicitly. - -This handler behaves like an [endpoint](REFERENCE.md#endpoint-block). It can have the same attributes **except** the following: - -- `access_control` -- `disable_access_control` -- `request_body_limit` - -Example: - -```hcl -error_handler "jwt_token_missing" { - error_file = "my_custom_file.html" - response {} -} -``` +and `proxy` block definitions and an [`error_handler` block](REFERENCE.md#error-handler-block) with the [related](#endpoint-error-types) type label. ## Error types diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md index f14b67706..1433c876e 100644 --- a/docs/REFERENCE.md +++ b/docs/REFERENCE.md @@ -26,6 +26,7 @@ - [SAML Block](#saml-block) - [Settings Block](#settings-block) - [Defaults Block](#defaults-block) + - [Error Handler Block](#error-handler-block) - [Access Control](#access-control) - [Health-Check](#health-check) - [Variables](#variables) @@ -105,7 +106,7 @@ as json error with an error body payload. This can be customized via `error_file |Block name|Context|Label|Nested block(s)| | :-----------| :-----------| :-----------| :-----------| -|`api`|[Server Block](#server-block)|Optional| [Endpoint Block(s)](#endpoint-block), [CORS Block](#cors-block), [Error Handler Block](ERRORS.md#error_handler-specification) | +|`api`|[Server Block](#server-block)|Optional| [Endpoint Block(s)](#endpoint-block), [CORS Block](#cors-block), [Error Handler Block(s)](#error-handler-block) | | Attribute(s) | Type |Default|Description|Characteristic(s)| Example| | :------------------------------ | :--------------- | :--------------- | :--------------- | :--------------- | :--------------- | @@ -126,7 +127,7 @@ produce an explicit or implicit client response. | Block name | Context | Label | Nested block(s) | |:-----------|:-------------------------------------------------------|:-----------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `endpoint` | [Server Block](#server-block), [API Block](#api-block) | ⚠ required, defines the path suffix for incoming client requests | [Proxy Block(s)](#proxy-block), [Request Block(s)](#request-block), [Response Block](#response-block), [Error Handler Block](ERRORS.md#error_handler-specification) | +| `endpoint` | [Server Block](#server-block), [API Block](#api-block) | ⚠ required, defines the path suffix for incoming client requests | [Proxy Block(s)](#proxy-block), [Request Block(s)](#request-block), [Response Block](#response-block), [Error Handler Block(s)](#error-handler-block) | @@ -211,7 +212,7 @@ The `backend` block defines the connection to a local/remote backend service. |Block name|Context|Label|Nested block(s)| | :----------| :-----------| :-----------| :-----------| -|`backend`| [Definitions Block](#definitions-block), [Proxy Block](#proxy-block), [Request Block](#request-block)| ⚠ required, when defined in [Definitions Block](#definitions-block)| [OpenAPI Block](#openapi-block), [OAuth2 CC Block](#oauth2-cc-block)| +|`backend`| [Definitions Block](#definitions-block), [Proxy Block](#proxy-block), [Request Block](#request-block), [OAuth2 CC Block](#oauth2-block), [JWT Block](#jwt-block), [OAuth2 AC Block (beta)](#beta-oauth2-block), [OIDC Block](#oidc-block)| ⚠ required, when defined in [Definitions Block](#definitions-block)| [OpenAPI Block](#openapi-block), [OAuth2 CC Block](#oauth2-block)| | Attribute(s) | Type |Default|Description|Characteristic(s)| Example| | :------------------------------ | :--------------- | :--------------- | :--------------- | :--------------- | :--------------- | @@ -285,6 +286,7 @@ The `cors` block configures the CORS (Cross-Origin Resource Sharing) behavior in **Note:** `Access-Control-Allow-Methods` is only sent in response to a CORS preflight request, if the method requested by `Access-Control-Request-Method` is an allowed method (see the `allowed_method` attribute for [`api`](#api-block) or [`endpoint`](#endpoint-block) blocks). + ### OAuth2 CC Block The `oauth2` block in the [Backend Block](#backend-block) context configures the OAuth2 Client Credentials flow to request a bearer token for the backend request. @@ -327,7 +329,7 @@ Use the `definitions` block to define configurations you want to reuse. |Block name|Context|Label|Nested block(s)| | :-----------| :-----------| :-----------| :-----------| -|`definitions`|-|no label|[Backend Block(s)](#backend-block), [Basic Auth Block(s)](#basic-auth-block), [JWT Block(s)](#jwt-block), [JWT Signing Profile Block(s)](#jwt-signing-profile-block), [SAML Block(s)](#saml-block), [OAuth2 AC Block(s)](#oauth2-ac-block-beta), [OIDC Block(s)](#oidc-block)| +|`definitions`|-|no label|[Backend Block(s)](#backend-block), [Basic Auth Block(s)](#basic-auth-block), [JWT Block(s)](#jwt-block), [JWT Signing Profile Block(s)](#jwt-signing-profile-block), [SAML Block(s)](#saml-block), [OAuth2 AC Block(s)](#beta-oauth2-block), [OIDC Block(s)](#oidc-block)| @@ -345,7 +347,7 @@ by `htpasswd_file` otherwise. | Block name | Context | Label | Nested block(s) | | :----------- | :------ | :---- | :-------------- | -| `basic_auth` | [Definitions Block](#definitions-block) | ⚠ required | [Error Handler Block](ERRORS.md#error_handler-specification) | +| `basic_auth` | [Definitions Block](#definitions-block) | ⚠ required | [Error Handler Block(s)](#error-handler-block) | | Attribute(s) | Type | Default | Description | Characteristic(s) | Example | | :-------------- | :----- | :------ | :---------- | :---------------- | :------ | @@ -368,7 +370,7 @@ Since responses from endpoints protected by JWT access controls are not publicly |Block name|Context|Label|Nested block(s)| | :-----------| :-----------| :-----------| :-----------| -| `jwt`| [Definitions Block](#definitions-block)| ⚠ required | [JWKS `backend`](#backend-block), [Error Handler Block](ERRORS.md#error_handler-specification) | +| `jwt`| [Definitions Block](#definitions-block)| ⚠ required | [JWKS `backend`](#backend-block), [Error Handler Block(s)](#error-handler-block) | | Attribute(s) | Type |Default|Description|Characteristic(s)| Example| | :-------- | :--------------- | :--------------- | :--------------- | :--------------- | :--------------- | @@ -433,6 +435,7 @@ An example can be found | `claims` |object|-|Default claims for the JWT payload.| The claim values are evaluated per request. |`claims = { iss = "https://the-issuer.com" }`| | `headers` | object | - | Additional header fields for the JWT. | `alg` and `typ` cannot be set. | `headers = { kid = "my-key-id" }` | + ### OAuth2 AC Block (Beta) The `beta_oauth2` block lets you configure the `oauth2_authorization_url()` [function](#functions) and an access @@ -441,7 +444,7 @@ Like all [Access Control](#access-control) types, the `beta_oauth2` block is def |Block name|Context|Label|Nested block(s)| | :-----------| :-----------| :-----------| :-----------| -|`beta_oauth2`| [Definitions Block](#definitions-block)| ⚠ required | [Backend Block](#backend-block), [Error Handler Block(s)](ERRORS.md#error_handler-specification) | +|`beta_oauth2`| [Definitions Block](#definitions-block)| ⚠ required | [Backend Block](#backend-block), [Error Handler Block](#error-handler-block) | | Attribute(s) | Type |Default|Description|Characteristic(s)| Example| | :------------------------------ | :--------------- | :--------------- | :--------------- | :--------------- | :--------------- | @@ -470,7 +473,7 @@ Like all [Access Control](#access-control) types, the `oidc` block is defined in |Block name|Context|Label|Nested block(s)| | :-----------| :-----------| :-----------| :-----------| -|`oidc`| [Definitions Block](#definitions-block)| ⚠ required | [Backend Block](#backend-block), [Error Handler Block(s)](ERRORS.md#error_handler-specification) | +|`oidc`| [Definitions Block](#definitions-block)| ⚠ required | [Backend Block](#backend-block), [Error Handler Block](#error-handler-block) | | Attribute(s) | Type |Default|Description|Characteristic(s)| Example| | :------------------------------ | :--------------- | :--------------- | :--------------- | :--------------- | :--------------- | @@ -500,7 +503,7 @@ required _label_. |Block name|Context|Label|Nested block(s)| | :--------| :-----------| :-----------| :-----------| -|`saml`| [Definitions Block](#definitions-block)| ⚠ required | [Error Handler Block](ERRORS.md#error_handler-specification) | +|`saml`| [Definitions Block](#definitions-block)| ⚠ required | [Error Handler Block](#error-handler-block) | | Attribute(s) | Type | Default | Description | Characteristic(s) | Example | | :------------------------------ | :--------------- | :--------------- | :--------------- | :--------------- | :--------------- | @@ -527,7 +530,7 @@ gateway instance. | Attribute(s) | Type | Default | Description | Characteristic(s) | Example | |:--------------------------------| :----- | :------------------ | :---------- | :---------------- | :------ | -| `accept_forwarded_url` | list | `[]` | Which `X-Forwarded-*` request headers should be accepted to change the [request variables](#request) `url`, `origin`, `protocol`, `host`, `port`. Valid values: `proto`, `host`, `port`. The port in `X-Forwarded-Port` takes precedence over a port in `X-Forwarded-Host`. | Affects relative url values for [`sp_acs_url`](#saml-block) attribute and `redirect_uri` attribute within [beta_oauth2](#oauth2-ac-block-beta) & [oidc](#oidc-block). | `["proto","host","port"]` | +| `accept_forwarded_url` | list | `[]` | Which `X-Forwarded-*` request headers should be accepted to change the [request variables](#request) `url`, `origin`, `protocol`, `host`, `port`. Valid values: `proto`, `host`, `port`. The port in `X-Forwarded-Port` takes precedence over a port in `X-Forwarded-Host`. | Affects relative url values for [`sp_acs_url`](#saml-block) attribute and `redirect_uri` attribute within [beta_oauth2](#beta-oauth2-block) & [oidc](#oidc-block). | `["proto","host","port"]` | | `default_port` | number | `8080` | Port which will be used if not explicitly specified per host within the [`hosts`](#server-block) list. |-|-| | `health_path` | string | `/healthz` | Health path which is available for all configured server and ports. |-|-| | `https_dev_proxy` | list | `[]` | List of tls port mappings to define the tls listen port and the target one. A self-signed certificate will be generated on the fly based on given hostname. | Certificates will be hold in memory and are generated once. | `["443:8080", "8443:8080"]` | @@ -562,6 +565,27 @@ Examples: - [`environment_variables`](https://github.com/avenga/couper-examples/blob/master/env-var/README.md). +### Error Handler Block + +The `error_handler` block lets you configure the handling of errors thrown in components configured by the parent blocks. + +The error handler label specifies which [error type](ERRORS.md#error-types) should be handled. Multiple labels are allowed. The label can be omitted to catch all relevant errors. This has the same behavior as the error type `*`, that catches all errors explicitly. + +Concerning child blocks and attributes, the `error_handler` block is similar to an [Endpoint Block](#endpoint-block). + +| Block name |Context|Label|Nested block(s)| +| :-----------| :-----------| :-----------| :-----------| +| `error_handler` | [API Block](#api-block), [Endpoint Block](#endpoint-block), [Basic Auth Block](#basic-auth-block), [JWT Block](#jwt-block), [OAuth2 AC Block (Beta)](#oauth2-ac-block-beta), [OIDC Block](#oidc-block), [SAML Block](#saml-block) | optional | [Proxy Block(s)](#proxy-block), [Request Block(s)](#request-block), [Response Block](#response-block), [Error Handler Block(s)](#error-handler-block) | + +| Attribute(s) | Type | Default | Description | Characteristic(s) | Example | +|:------------------------|:-----------------|:--------|:------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------| +| `custom_log_fields` | map | - | Defines log fields for [Custom Logging](LOGS.md#custom-logging). | ⚠ Inherited by nested blocks. | - | +| [Modifiers](#modifiers) | - | - | - | - | - | + +Examples: + +- [Error Handling for Access Controls](https://github.com/avenga/couper-examples/blob/master/error-handling-ba/README.md). + ## Access Control The configuration of access control is twofold in Couper: You define the particular @@ -644,7 +668,7 @@ For a [SAML Block](#saml-block) the variable contains - `exp`: optional expiration date (value of `SessionNotOnOrAfter` of the SAML assertion) - `attributes`: a map of attributes from the SAML assertion -For an [OAuth2 AC Block](#oauth2-ac-block-beta), the variable contains the response from the token endpoint, e.g. +For an [OAuth2 AC Block](#beta-oauth2-block), the variable contains the response from the token endpoint, e.g. - `access_token`: the access token retrieved from the token endpoint - `token_type`: the token type @@ -723,7 +747,7 @@ To access the HTTP status code of the `default` response use `backend_responses. | `length` | integer | Returns the number of elements in the given collection. | `collection` (tuple, list or map; **no object**) | `length([0,1,2,3])` | | `lookup` | various | Performs a dynamic lookup into a map. The default (third argument) is returned if the key (second argument) is not found in the inputMap (first argument). | `inputMap` (object or map), `key` (string), `default` (various) | `lookup({a = 1}, "b", "def")` | | `merge` | object or tuple | Deep-merges two or more of either objects or tuples. `null` arguments are ignored. A `null` attribute value in an object removes the previous attribute value. An attribute value with a different type than the current value is set as the new value. `merge()` with no parameters returns `null`. | `arg...` (object or tuple) | `merge(request.headers, { x-additional = "myval" })` | -| `oauth2_authorization_url` | string | Creates an OAuth2 authorization URL from a referenced [OAuth2 AC Block](#oauth2-ac-block-beta) or [OIDC Block](#oidc-block). | `label` (string) | `oauth2_authorization_url("myOAuth2")` | +| `oauth2_authorization_url` | string | Creates an OAuth2 authorization URL from a referenced [OAuth2 AC Block](#beta-oauth2-block) or [OIDC Block](#oidc-block). | `label` (string) | `oauth2_authorization_url("myOAuth2")` | | `oauth2_verifier` | string | Creates a cryptographically random key as specified in RFC 7636, applicable for all verifier methods; e.g. to be set as a cookie and read into `verifier_value`. Multiple calls of this function in the same client request context return the same value. | | `oauth2_verifier()` | | `relative_url` | string | Returns a relative URL by retaining `path`, `query` and `fragment` components. The input URL `s` must begin with `/`, `//`, `http://` or `https://`, otherwise an error is thrown. | s (string) | `relative_url("https://httpbin.org/anything?query#fragment") // returns "/anything?query#fragment"` | | `saml_sso_url` | string | Creates a SAML SingleSignOn URL (including the `SAMLRequest` parameter) from a referenced [SAML Block](#saml-block). | `label` (string) | `saml_sso_url("mySAML")` | @@ -752,9 +776,9 @@ executed ordered as follows: | Modifier | Contexts | Description | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------- | -| `remove_request_headers` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | list of request header to be removed from the upstream request. | -| `set_request_headers` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to set request header in the upstream request. | -| `add_request_headers` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to add request header to the upstream request. | +| `remove_request_headers` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | list of request header to be removed from the upstream request. | +| `set_request_headers` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to set request header in the upstream request. | +| `add_request_headers` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to add request header to the upstream request. | All `*_request_headers` are executed from: `endpoint`, `proxy`, `backend` and `error_handler`. @@ -766,9 +790,9 @@ executed ordered as follows: | Modifier | Contexts | Description | | :------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------- | -| `remove_response_headers` | [Server Block](#server-block), [Files Block](#files-block), [SPA Block](#spa-block), [API Block](#api-block), [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | list of response header to be removed from the client response. | -| `set_response_headers` | [Server Block](#server-block), [Files Block](#files-block), [SPA Block](#spa-block), [API Block](#api-block), [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to set response header in the client response. | -| `add_response_headers` | [Server Block](#server-block), [Files Block](#files-block), [SPA Block](#spa-block), [API Block](#api-block), [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to add response header to the client response. | +| `remove_response_headers` | [Server Block](#server-block), [Files Block](#files-block), [SPA Block](#spa-block), [API Block](#api-block), [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | list of response header to be removed from the client response. | +| `set_response_headers` | [Server Block](#server-block), [Files Block](#files-block), [SPA Block](#spa-block), [API Block](#api-block), [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to set response header in the client response. | +| `add_response_headers` | [Server Block](#server-block), [Files Block](#files-block), [SPA Block](#spa-block), [API Block](#api-block), [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to add response header to the client response. | All `*_response_headers` are executed from: `server`, `files`, `spa`, `api`, `endpoint`, `proxy`, `backend` and `error_handler`. @@ -779,7 +803,7 @@ given value. | Modifier | Contexts | Description | | :-------------------- | :-------------------------------------------------------------------------------------------------- | :------------------------------------------------- | -| `set_response_status` | [Endpoint Block](#endpoint-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | HTTP status code to be set to the client response. | +| `set_response_status` | [Endpoint Block](#endpoint-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | HTTP status code to be set to the client response. | If the HTTP status code ist set to `204`, the response body and the HTTP header field `Content-Length` is removed from the client response, and a warning is logged. @@ -794,9 +818,9 @@ executed ordered as follows: | Modifier | Contexts | Description | | :-------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------- | -| `remove_query_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | list of query parameters to be removed from the upstream request URL. | -| `set_query_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to set query parameters in the upstream request URL. | -| `add_query_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to add query parameters to the upstream request URL. | +| `remove_query_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | list of query parameters to be removed from the upstream request URL. | +| `set_query_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to set query parameters in the upstream request URL. | +| `add_query_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to add query parameters to the upstream request URL. | All `*_query_params` are executed from: `endpoint`, `proxy`, `backend` and `error_handler`. @@ -840,9 +864,9 @@ executed ordered as follows: | Modifier | Contexts | Description | | :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------- | -| `remove_form_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | list of form parameters to be removed from the upstream request body. | -| `set_form_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to set form parameters in the upstream request body. | -| `add_form_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](ERRORS.md#error_handler-specification) | Key/value(s) pairs to add form parameters to the upstream request body. | +| `remove_form_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | list of form parameters to be removed from the upstream request body. | +| `set_form_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to set form parameters in the upstream request body. | +| `add_form_params` | [Endpoint Block](#endpoint-block), [Proxy Block](#proxy-block), [Backend Block](#backend-block), [Error Handler](#error-handler-block) | Key/value(s) pairs to add form parameters to the upstream request body. | All `*_form_params` are executed from: `endpoint`, `proxy`, `backend` and `error_handler`. diff --git a/docs/docs_test.go b/docs/docs_test.go index 285ee6578..5cd4d2e0e 100644 --- a/docs/docs_test.go +++ b/docs/docs_test.go @@ -22,7 +22,7 @@ func TestDocs_Links(t *testing.T) { } type entry struct { - anchors, links []item + anchors, htmlAnchors, links []item } entries := map[string]*entry{} @@ -67,16 +67,24 @@ func TestDocs_Links(t *testing.T) { anchors = append(anchors, item{value: prepareAnchor(match[1])}) } + regexHTMLAnchors := regexp.MustCompile(`(?m)^$`) + allHTMLAnchors := regexHTMLAnchors.FindAllStringSubmatch(string(raw), -1) + var htmlAnchors []item + for _, match := range allHTMLAnchors { + htmlAnchors = append(htmlAnchors, item{value: match[1]}) + } + entries[file.Name()] = &entry{ - anchors: anchors, - links: links, + anchors: anchors, + htmlAnchors: htmlAnchors, + links: links, } } for filename, file := range entries { // Search for ghost-anchors for _, link := range file.links { - if !existsFn(file.anchors, link) { + if !existsFn(file.anchors, link) && !existsFn(file.htmlAnchors, link) { val := link.value if link.reference != "" { val = link.reference + ":" + val @@ -85,7 +93,7 @@ func TestDocs_Links(t *testing.T) { } } - // Search for ghost-links + // Search for ghost-links - ignore HTML anchors added specifically for VS Code. for _, anchor := range file.anchors { if anchor.value != "table-of-contents" && !existsFn(file.links, anchor) { t.Errorf("%s: link for '%v' not found", filename, anchor)