Skip to content

Commit

Permalink
Generic error types (#500)
Browse files Browse the repository at this point in the history
* new catchable error type 'endpoint'

* remove code markers as the backend error type is not handled in a backend block

* Document access_control error type as catchable error and super-type for other types

* table formatting

* add introductory sentence to error types tables

* new test case: errors of unexpected_status type can be handled with `error_handler "endpoint"`

* existing test case: error type unexpected_status more specific than endpoint

* changelog for new error types; add link to another entry
  • Loading branch information
johakoch authored May 9, 2022
1 parent 502ef91 commit ce9bd68
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 21 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ Unreleased changes are available as `avenga/couper:edge` container.
* `backends.<name>.health` variable to access the current health-check state _(subject to change)_
* Log malformed duration settings ([#487](https://github.com/avenga/couper/pull/487))
* `url` attribute could make use of our wildcard pattern `/**` and relative urls in combination with a backend reference ([#480](https://github.com/avenga/couper/pull/480))
* Error handling for `backend`, `backend_openapi_validation` and `backend_timeout` error types ([#490](https://github.com/avenga/couper/pull/490))
* Error handling for `backend`, `backend_openapi_validation` and `backend_timeout` [error types](./docs/ERRORS.md) ([#490](https://github.com/avenga/couper/pull/490))
* `response.bytes` log-field to backend logs if read from body, fallback is the `Content-Length` header ([#494](https://github.com/avenga/couper/pull/494))
* [Error types](./docs/ERRORS.md) `endpoint` and `access_control` ([#500](https://github.com/avenga/couper/pull/500))

* **Changed**
* Permission handling: ([#477](https://github.com/avenga/couper/pull/477))
Expand Down
46 changes: 28 additions & 18 deletions docs/ERRORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,43 @@ All errors have a specific type. You can find it in the log field `error_type`.

### Access control error types

The following table documents error types that can be handled in the respective access control blocks (`basic_auth`, `jwt`, `saml`, `beta_oauth2`, `oidc`):

| Type (and super types) | Description | Default handling |
|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------|
| `basic_auth` | All `basic_auth` related errors, e.g. unknown user or wrong password. | Send error template with status `401` and `WWW-Authenticate: Basic` header. |
| `access_control` | Access control related errors | Send error template with status `403`. |
| `basic_auth` (`access_control`) | All `basic_auth` related errors, e.g. unknown user or wrong password. | Send error template with status `401` and `WWW-Authenticate: Basic` header. |
| `basic_auth_credentials_missing` (`basic_auth`) | Client does not provide any credentials. | Send error template with status `401` and `WWW-Authenticate: Basic` header. |
| `jwt` | All `jwt` related errors. | Send error template with status `403`. |
| `jwt` (`access_control`) | All `jwt` related errors. | Send error template with status `403`. |
| `jwt_token_missing` (`jwt`) | No token provided with configured token source. | Send error template with status `401`. |
| `jwt_token_expired` (`jwt`) | Given token is valid but expired. | Send error template with status `403`. |
| `jwt_token_invalid` (`jwt`) | The token is syntactically not a JWT, or not sufficient, e.g. because required claims are missing or have unexpected values. | Send error template with status `403`. |
| `saml` (or `saml2`) | All `saml` related errors | Send error template with status `403`. |
| `oauth2` | All `beta_oauth2`/`oidc` related errors | Send error template with status `403`. |
| `saml` (or `saml2`) (`access_control`) | All `saml` related errors | Send error template with status `403`. |
| `oauth2` (`access_control`) | All `beta_oauth2`/`oidc` related errors | Send error template with status `403`. |

### API error types

| Type (and super types) | Description | Default handling |
|:------------------------------------------------|:--------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------|
| `backend` | All catchable `backend` related errors | Send error template with status `502`. |
| `backend_openapi_validation` (`backend`) | Backend request or response is invalid | Send error template with status code `400` for invalid backend request or `502` for invalid backend response. |
| `backend_timeout` (`backend`) | A backend request timed out | Send error template with status `504`. |
| `beta_insufficient_permissions` | The permission required for the requested operation is not in the permissions granted to the requester. | Send error template with status `403`. |
The following table documents error types that can be handled in `api` blocks:

| Type (and super types) | Description | Default handling |
|:---------------------------------------------------|:--------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------|
| `backend` | All catchable backend related errors | Send error template with status `502`. |
| `backend_openapi_validation` (`backend`) | Backend request or response is invalid | Send error template with status code `400` for invalid backend request or `502` for invalid backend response. |
| `backend_timeout` (`backend`) | A backend request timed out | Send error template with status `504`. |
| `access_control` | Access control related errors | Send error template with status `403`. |
| `beta_insufficient_permissions` (`access_control`) | The permission required for the requested operation is not in the permissions granted to the requester. | Send error template with status `403`. |

### Endpoint error types

| Type (and super types) | Description | Default handling |
|:------------------------------------------------|:--------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------|
| `backend` | All catchable `backend` related errors | Send error template with status `502`. |
| `backend_openapi_validation` (`backend`) | Backend request or response is invalid | Send error template with status code `400` for invalid backend request or `502` for invalid backend response. |
| `backend_timeout` (`backend`) | A backend request timed out | Send error template with status `504`. |
| `beta_insufficient_permissions` | The permission required for the requested operation is not in the permissions granted to the requester. | Send error template with status `403`. |
| `sequence` | A `request` or `proxy` block request has been failed while depending on another one | Send error template with status `502`. |
| `unexpected_status` | A `request` or `proxy` block response status code does not match the to `expected_status` list | Send error template with status `502`. |
The following table documents error types that can be handled in `endpoint` blocks:

| Type (and super types) | Description | Default handling |
|:---------------------------------------------------|:--------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------|
| `backend` | All catchable backend related errors | Send error template with status `502`. |
| `backend_openapi_validation` (`backend`) | Backend request or response is invalid | Send error template with status code `400` for invalid backend request or `502` for invalid backend response. |
| `backend_timeout` (`backend`) | A backend request timed out | Send error template with status `504`. |
| `access_control` | Access control related errors | Send error template with status `403`. |
| `beta_insufficient_permissions` (`access_control`) | The permission required for the requested operation is not in the permissions granted to the requester. | Send error template with status `403`. |
| `endpoint` | All catchable `endpoint` related errors | Send error template with status `502`. |
| `sequence` (`endpoint`) | A `request` or `proxy` block request has been failed while depending on another one | Send error template with status `502`. |
| `unexpected_status` (`endpoint`) | A `request` or `proxy` block response status code does not match the to `expected_status` list | Send error template with status `502`. |
1 change: 1 addition & 0 deletions errors/type_defintions.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var Definitions = []*Error{
Backend.Kind("backend_openapi_validation").Status(http.StatusBadRequest),
Backend.Kind("backend_timeout").Status(http.StatusGatewayTimeout),

Endpoint,
Endpoint.Kind("sequence"),
Endpoint.Kind("unexpected_status"),
}
5 changes: 3 additions & 2 deletions errors/types_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/http_endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@ func TestEndpointErrorHandler(t *testing.T) {
for _, tc := range []testcase{
{"error_handler not triggered", "/ok", test.Header{"x": "application/json"}, http.StatusOK, ""},
{"error_handler triggered with beresp body", "/not-ok", test.Header{"x": "200", "y": "item1"}, http.StatusTeapot, "unexpected_status"},
{"error_handler triggered with beresp body handled by endpoint", "/not-ok-endpoint", test.Header{"x": "200", "y": "item1"}, http.StatusTeapot, "unexpected_status"},
{"error_handler triggered with beresp body - sequence", "/not-ok-sequence", test.Header{"x": "application/json"}, http.StatusTeapot, "unexpected_status"},
} {
t.Run(tc.name, func(st *testing.T) {
Expand Down
24 changes: 24 additions & 0 deletions server/testdata/endpoints/14_couper.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ server { # error_handler
expected_status = [418]
}

error_handler "endpoint" {
response {
status = 417
}
}

error_handler "unexpected_status" {
response {
headers = {
Expand All @@ -43,6 +49,24 @@ server { # error_handler
}
}

endpoint "/not-ok-endpoint" {
request {
url = "${env.COUPER_TEST_BACKEND_ADDR}/anything"

expected_status = [418]
}

error_handler "endpoint" {
response {
headers = {
x = backend_responses.default.status
y = backend_responses.default.json_body.Json.list[0]
}
status = 418
}
}
}

endpoint "/not-ok-sequence" {
request "resolve" {
url = "${env.COUPER_TEST_BACKEND_ADDR}/anything"
Expand Down

0 comments on commit ce9bd68

Please sign in to comment.