Skip to content
Permalink
Browse files

Add support for error pages for VS/VSR

  • Loading branch information
Rulox committed Dec 6, 2019
1 parent 65c0fef commit c2bccae7a052538d2c7fc96a6f891ad45e2d9101
@@ -28,6 +28,9 @@ This document is the reference documentation for the resources. To see additiona
- [Split](#split)
- [Match](#match)
- [Condition](#condition)
- [ErrorPage](#errorpage)
- [ErrorPage.Redirect](#errorpage-redirect)
- [ErrorPage.Return](#errorpage-return)
- [Using VirtualServer and VirtualServerRoute](#using-virtualserver-and-virtualserverroute)
- [Validation](#validation)
- [Customization via ConfigMap](#customization-via-configmap)
@@ -186,6 +189,10 @@ The route defines rules for matching client requests to actions like passing a r
- The name of a VirtualServerRoute resource that defines this route. If the VirtualServerRoute belongs to a different namespace than the VirtualServer, you need to include the namespace. For example, ``tea-namespace/tea``.
- ``string``
- No*
* - ``errorPages``
- The custom responses for error codes. NGINX will use those responses instead of returning the error responses from the upstream servers or the default responses generated by NGINX. A custom response can be a redirect or a canned response. For example, a redirect to another URL if an upstream server responded with a 404 status code.
- `[]errorPage <#errorpage>`_
- No
```

\* -- a route must include exactly one of the following: `action`, `splits`, or `route`.
@@ -299,6 +306,10 @@ action:
- The matching rules for advanced content-based routing. Requires the default ``action`` or ``splits``. Unmatched requests will be handled by the default ``action`` or ``splits``.
- `matches <#match>`_
- No
* - ``errorPages``
- The custom responses for error codes. NGINX will use those responses instead of returning the error responses from the upstream servers or the default responses generated by NGINX. A custom response can be a redirect or a canned response. For example, a redirect to another URL if an upstream server responded with a 404 status code.
- `[]errorPage <#errorpage>`_
- No
```

\* -- a subroute must include exactly one of the following: `action` or `splits`.
@@ -930,6 +941,148 @@ The value supports two kinds of matching:

**Note**: a value must not include any unescaped double quotes (`"`) and must not end with an unescaped backslash (`\`). For example, the following are invalid values: `some"value`, `somevalue\`.


### ErrorPage

The errorPage defines a custom response for a route for the case when either an upstream server responds with (or NGINX generates) an error status code. The custom response can be a redirect or a canned response. See the [error_page](https://nginx.org/en/docs/http/ngx_http_core_module.html#error_page) directive for more information.
```yaml
path: /coffee
errorPages:
- codes: [502, 503]
redirect:
code: 301
url: https://nginx.org
- codes: [404]
return:
code: 200
body: "Original resource not found, but success!"
```

```eval_rst
.. list-table::
:header-rows: 1
* - Field
- Description
- Type
- Required
* - ``codes``
- A list of error status codes.
- ``[]int``
- Yes
* - ``redirect``
- The redirect action for the given status codes.
- `errorPage.Redirect <#errorpage-redirect>`_
- No*
* - ``return``
- The canned response action for the given status codes.
- `errorPage.Return <#errorpage-return>`_
- No*
```

\* -- an errorPage must include exactly one of the following: `return` or `redirect`.

### ErrorPage.Redirect

The redirect defines a redirect for an errorPage.

In the example below, NGINX responds with a redirect when a response from an upstream server has a 404 status code.

```yaml
codes: [404]
redirect:
code: 301
url: ${scheme}://cafe.example.com/error_${status}.html
```

```eval_rst
.. list-table::
:header-rows: 1
* - Field
- Description
- Type
- Required
* - ``code``
- The status code of a redirect. The allowed values are: ``301``\ , ``302``\ , ``307``\ , ``308``. The default is ``301``.
- ``int``
- No
* - ``url``
- The URL to redirect the request to. Supported NGINX variables: ``$scheme``\ , ``$status``\ and ``$http_x_forwarded_proto``\. Variables must be inclosed in curly braces. For example: ``${scheme}``.
- ``string``
- Yes
```

### ErrorPage.Return

The return defines a canned response for an errorPage.

In the example below, NGINX responds with a canned response when a response from an upstream server has either 401 or 403 status code.

```yaml
codes: [401, 403]
return:
code: 200
type: application/json
body: "{\"msg\": \"You don't have permission to do this\"}"
headers:
- name: x-debug-original-status
value: ${status}
```

```eval_rst
.. list-table::
:header-rows: 1
* - Field
- Description
- Type
- Required
* - ``code``
- The status code of the response. The default is the status code of the original response.
- ``int``
- No
* - ``type``
- The MIME type of the response. The default is ``text/html``.
- ``string``
- No
* - ``body``
- The body of the response. Supported NGINX variable: ``$status`` \ . Variables must be inclosed in curly braces. For example: ``${status}``.
- ``string``
- Yes
* - ``headers``
- The custom headers of the response.
- `errorPage.Redirect.Header <#errorpage-return-header>`_
- No
```

### ErrorPage.Return.Header

The header defines an HTTP Header for a canned response in an errorPage:

```yaml
name: x-debug-original-status
value: ${status}
```

```eval_rst
.. list-table::
:header-rows: 1
* - Field
- Description
- Type
- Required
* - ``name``
- The name of the header.
- ``string``
- Yes
* - ``value``
- The value of the header. Supported NGINX variables: ``$status`` \ . Variables must be inclosed in curly braces. For example: ``${status}``.
- ``string``
- No
```

## Using VirtualServer and VirtualServerRoute

You can use the usual `kubectl` commands to work with VirtualServer and VirtualServerRoute resources, similar to Ingress resources.
@@ -43,6 +43,7 @@ type Server struct {
Snippets []string
InternalRedirectLocations []InternalRedirectLocation
Locations []Location
ErrorPageLocations []ErrorPageLocation
HealthChecks []HealthCheck
TLSRedirect *TLSRedirect
}
@@ -58,6 +59,7 @@ type SSL struct {
// Location defines a location.
type Location struct {
Path string
Internal bool
Snippets []string
ProxyConnectTimeout string
ProxyReadTimeout string
@@ -71,9 +73,11 @@ type Location struct {
ProxyNextUpstream string
ProxyNextUpstreamTimeout string
ProxyNextUpstreamTries int
ProxyInterceptErrors bool
HasKeepalive bool
DefaultType string
Return *Return
ErrorPages []ErrorPage
}

// SplitClient defines a split_clients.
@@ -89,6 +93,27 @@ type Return struct {
Text string
}

// ErrorPage defines an error_page of a location.
type ErrorPage struct {
Name string
Codes string
ResponseCode int
}

// ErrorPageLocation defines a named location for an error_page directive.
type ErrorPageLocation struct {
Name string
DefaultType string
Return *Return
Headers []Header
}

// Header defines a header to use with add_header directive.
type Header struct {
Name string
Value string
}

// HealthCheck defines a HealthCheck for an upstream in a Server.
type HealthCheck struct {
Name string
@@ -88,8 +88,7 @@ server {

{{ range $l := $s.InternalRedirectLocations }}
location {{ $l.Path }} {
error_page 418 = {{ $l.Destination }};
return 418;
rewrite ^ {{ $l.Destination }} last;
}
{{ end }}

@@ -107,8 +106,24 @@ server {
}
{{ end }}

{{ range $e := $s.ErrorPageLocations }}
location {{ $e.Name }} {
{{ if $e.DefaultType }}
default_type "{{ $e.DefaultType }}";
{{ end }}
{{ range $h := $e.Headers }}
add_header {{ $h.Name }} "{{ $h.Value }}" always;
{{ end }}
# status code is ignored here, using 0
return 0 "{{ $e.Return.Text }}";
}
{{ end }}

{{ range $l := $s.Locations }}
location {{ $l.Path }} {
{{ if $l.Internal }}
internal;
{{ end }}
{{ range $snippet := $l.Snippets }}
{{ $snippet }}
{{ end }}
@@ -121,6 +136,10 @@ server {
{{ end }}

{{ if $l.ProxyPass }}
{{ range $e := $l.ErrorPages }}
error_page {{ $e.Codes }} {{ if ne 0 $e.ResponseCode }}={{ $e.ResponseCode }}{{ end }} "{{ $e.Name }}";
{{ end }}

proxy_connect_timeout {{ $l.ProxyConnectTimeout }};
proxy_read_timeout {{ $l.ProxyReadTimeout }};
proxy_send_timeout {{ $l.ProxySendTimeout }};
@@ -137,7 +156,9 @@ server {
{{ if $l.ProxyBufferSize }}
proxy_buffer_size {{ $l.ProxyBufferSize }};
{{ end }}

{{ if $l.ProxyInterceptErrors }}
proxy_intercept_errors on;
{{ end }}
proxy_http_version 1.1;

set $default_connection_header {{ if $l.HasKeepalive }}""{{ else }}close{{ end }};
@@ -71,13 +71,28 @@ server {

{{ range $l := $s.InternalRedirectLocations }}
location {{ $l.Path }} {
error_page 418 = {{ $l.Destination }};
return 418;
rewrite ^ {{ $l.Destination }} last;
}
{{ end }}

{{ range $e := $s.ErrorPageLocations }}
location {{ $e.Name }} {
{{ if $e.DefaultType }}
default_type "{{ $e.DefaultType }}";
{{ end }}
{{ range $h := $e.Headers }}
add_header {{ $h.Name }} "{{ $h.Value }}" always;
{{ end }}
# status code is ignored here, using 0
return 0 "{{ $e.Return.Text }}";
}
{{ end }}

{{ range $l := $s.Locations }}
location {{ $l.Path }} {
{{ if $l.Internal }}
internal;
{{ end }}
{{ range $snippet := $l.Snippets }}
{{ $snippet }}
{{ end }}
@@ -90,6 +105,10 @@ server {
{{ end }}

{{ if $l.ProxyPass }}
{{ range $e := $l.ErrorPages }}
error_page {{ $e.Codes }} {{ if ne 0 $e.ResponseCode }}={{ $e.ResponseCode }}{{ end }} "{{ $e.Name }}";
{{ end }}

proxy_connect_timeout {{ $l.ProxyConnectTimeout }};
proxy_read_timeout {{ $l.ProxyReadTimeout }};
proxy_send_timeout {{ $l.ProxySendTimeout }};
@@ -106,7 +125,9 @@ server {
{{ if $l.ProxyBufferSize }}
proxy_buffer_size {{ $l.ProxyBufferSize }};
{{ end }}

{{ if $l.ProxyInterceptErrors }}
proxy_intercept_errors on;
{{ end }}
proxy_http_version 1.1;

set $default_connection_header {{ if $l.HasKeepalive }}""{{ else }}close{{ end }};

0 comments on commit c2bccae

Please sign in to comment.
You can’t perform that action at this time.