Hello, A recent RFC (7725) has introduced HTTP Return Code 451 to be returned when access to a resource is forbidden for legal reasons [1]. In addition to the return code, HTTP server may return an additional “Link” field in HTTP header. The new header should be formatted as below:
Link: <https://spqr.example.org/legislatione>; rel="blocked-by" Please also note that the new Relation Name (blocked-by) is also added to IANA Link Relation Type Registry [2]. A user may simply return a 451 code based on a condition or additionally provide a link to a URL (usually pointed to the applicable legislation or regulation): if ($http_user_agent !~ MSIE) { return 451 https://spqr.example.org/legislatione; } if ($http_user_agent ~* (Wget) ) { return 451; } Here is the proposed patch: # HG changeset patch # User Babak Farrokhi <ba...@farrokhi.net> # Date 1479886479 -12600 # Wed Nov 23 11:04:39 2016 +0330 # Node ID d56f78822c5bcaa8bde2d95c862d06491618154c # Parent 2c7a2d75938a31044552b0a6cd6edaebdaf0bd69 Add support for HTTP 451 Return Code (RFC 7725) RFC 7725 introduced HTTP 451 “Unavailable For Legal Reasons” return code, to be returned when the user requests a resource which cannot be served for legal reasons. It also introduces an optional "Link" header field that should contain a link to relevant webpage (e.g. legal documents) with following format: Link: <https://spqr.example.org/legislatione>; rel="blocked-by" A user can now configure nginx to return this code using a return clause in configuration file: if ($http_user_agent !~ MSIE) { return 451 https://spqr.example.org/legislatione; } if ($http_user_agent ~* (Wget) ) { return 451; } Please note that the URL is optional and if not specified, no "Link" field will be added to header. diff -r 2c7a2d75938a -r d56f78822c5b src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm Mon Nov 21 16:49:19 2016 +0300 +++ b/src/http/modules/perl/nginx.pm Wed Nov 23 11:04:39 2016 +0330 @@ -88,6 +88,7 @@ use constant HTTP_REQUEST_URI_TOO_LARGE => 414; use constant HTTP_UNSUPPORTED_MEDIA_TYPE => 415; use constant HTTP_RANGE_NOT_SATISFIABLE => 416; +use constant HTTP_NOT_ALLOWED_LEGALLY => 451; use constant HTTP_INTERNAL_SERVER_ERROR => 500; use constant HTTP_SERVER_ERROR => 500; diff -r 2c7a2d75938a -r d56f78822c5b src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c Mon Nov 21 16:49:19 2016 +0300 +++ b/src/http/ngx_http_core_module.c Wed Nov 23 11:04:39 2016 +0330 @@ -1862,6 +1862,7 @@ ngx_str_t val; ngx_buf_t *b; ngx_chain_t out; + ngx_str_t link; if (ngx_http_discard_request_body(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -1873,6 +1874,32 @@ return NGX_HTTP_INTERNAL_SERVER_ERROR; } + if (status == NGX_HTTP_NOT_ALLOWED_LEGALLY) { + ngx_http_clear_link(r); + + r->headers_out.link = ngx_list_push(&r->headers_out.headers); + if (r->headers_out.link == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + r->headers_out.link->hash = 1; + ngx_str_set(&r->headers_out.link->key, "Link"); + + link.data = ngx_pcalloc(r->pool, val.len + + ngx_strlen("<>; rel=\"blocked-by\"")); + if (link.data == NULL) { + r->headers_out.link->hash = 0; + return NGX_ERROR; + } + + link.len = ngx_sprintf(link.data, "<%s>; rel=\"blocked-by\"", + val.data) - link.data; + + r->headers_out.link->value = link; + + return status; + } + if (status == NGX_HTTP_MOVED_PERMANENTLY || status == NGX_HTTP_MOVED_TEMPORARILY || status == NGX_HTTP_SEE_OTHER diff -r 2c7a2d75938a -r d56f78822c5b src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h Mon Nov 21 16:49:19 2016 +0300 +++ b/src/http/ngx_http_core_module.h Wed Nov 23 11:04:39 2016 +0330 @@ -570,6 +570,13 @@ r->headers_out.location = NULL; \ } +#define ngx_http_clear_link(r) \ + \ + if (r->headers_out.link) { \ + r->headers_out.link->hash = 0; \ + r->headers_out.link = NULL; \ + } + #define ngx_http_clear_etag(r) \ \ if (r->headers_out.etag) { \ diff -r 2c7a2d75938a -r d56f78822c5b src/http/ngx_http_header_filter_module.c --- a/src/http/ngx_http_header_filter_module.c Mon Nov 21 16:49:19 2016 +0300 +++ b/src/http/ngx_http_header_filter_module.c Wed Nov 23 11:04:39 2016 +0330 @@ -100,12 +100,38 @@ ngx_null_string, /* "419 unused" */ ngx_null_string, /* "420 unused" */ ngx_string("421 Misdirected Request"), + ngx_null_string, /* "422 Unprocessable Entity" */ + ngx_null_string, /* "423 Locked" */ + ngx_null_string, /* "424 Failed Dependency" */ + ngx_null_string, /* "425 unused" */ + ngx_null_string, /* "426 Upgrade Required" */ + ngx_null_string, /* "427 unused" */ + ngx_null_string, /* "428 Precondition Required" */ + ngx_null_string, /* "429 Too Many Requests" */ + ngx_null_string, /* "430 unused" */ + ngx_null_string, /* "431 Request Header Fields Too Large" */ + ngx_null_string, /* "432 unused" */ + ngx_null_string, /* "433 unused" */ + ngx_null_string, /* "434 unused" */ + ngx_null_string, /* "435 unused" */ + ngx_null_string, /* "436 unused" */ + ngx_null_string, /* "437 unused" */ + ngx_null_string, /* "438 unused" */ + ngx_null_string, /* "439 unused" */ + ngx_null_string, /* "440 unused" */ + ngx_null_string, /* "441 unused" */ + ngx_null_string, /* "442 unused" */ + ngx_null_string, /* "443 unused" */ + ngx_null_string, /* "444 unused" */ + ngx_null_string, /* "445 unused" */ + ngx_null_string, /* "446 unused" */ + ngx_null_string, /* "447 unused" */ + ngx_null_string, /* "448 unused" */ + ngx_null_string, /* "449 unused" */ + ngx_null_string, /* "450 unused" */ + ngx_string("451 Unavailable For Legal Reasons"), - /* ngx_null_string, */ /* "422 Unprocessable Entity" */ - /* ngx_null_string, */ /* "423 Locked" */ - /* ngx_null_string, */ /* "424 Failed Dependency" */ - -#define NGX_HTTP_LAST_4XX 422 +#define NGX_HTTP_LAST_4XX 452 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string("500 Internal Server Error"), @@ -133,6 +159,7 @@ offsetof(ngx_http_headers_out_t, content_length) }, { ngx_string("Content-Encoding"), offsetof(ngx_http_headers_out_t, content_encoding) }, + { ngx_string("Link"), offsetof(ngx_http_headers_out_t, link) }, { ngx_string("Location"), offsetof(ngx_http_headers_out_t, location) }, { ngx_string("Last-Modified"), offsetof(ngx_http_headers_out_t, last_modified) }, diff -r 2c7a2d75938a -r d56f78822c5b src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h Mon Nov 21 16:49:19 2016 +0300 +++ b/src/http/ngx_http_request.h Wed Nov 23 11:04:39 2016 +0330 @@ -97,6 +97,7 @@ #define NGX_HTTP_RANGE_NOT_SATISFIABLE 416 #define NGX_HTTP_MISDIRECTED_REQUEST 421 +#define NGX_HTTP_NOT_ALLOWED_LEGALLY 451 /* Our own HTTP codes */ @@ -253,6 +254,7 @@ ngx_table_elt_t *date; ngx_table_elt_t *content_length; ngx_table_elt_t *content_encoding; + ngx_table_elt_t *link; ngx_table_elt_t *location; ngx_table_elt_t *refresh; ngx_table_elt_t *last_modified; diff -r 2c7a2d75938a -r d56f78822c5b src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c Mon Nov 21 16:49:19 2016 +0300 +++ b/src/http/ngx_http_special_response.c Wed Nov 23 11:04:39 2016 +0330 @@ -217,6 +217,12 @@ "<center><h1>421 Misdirected Request</h1></center>" CRLF ; +static char ngx_http_error_451_page[] = +"<html>" CRLF +"<head><title>451 Unavailable For Legal Reasons</title></head>" CRLF +"<body bgcolor=\"white\">" CRLF +"<center><h1>451 Unavailable For Legal Reasons</h1></center>" CRLF +; static char ngx_http_error_494_page[] = "<html>" CRLF @@ -347,8 +353,38 @@ ngx_null_string, /* 419 */ ngx_null_string, /* 420 */ ngx_string(ngx_http_error_421_page), + ngx_null_string, /* 422 */ + ngx_null_string, /* 423 */ + ngx_null_string, /* 424 */ + ngx_null_string, /* 425 */ + ngx_null_string, /* 426 */ + ngx_null_string, /* 427 */ + ngx_null_string, /* 428 */ + ngx_null_string, /* 429 */ + ngx_null_string, /* 430 */ + ngx_null_string, /* 431 */ + ngx_null_string, /* 432 */ + ngx_null_string, /* 433 */ + ngx_null_string, /* 434 */ + ngx_null_string, /* 435 */ + ngx_null_string, /* 436 */ + ngx_null_string, /* 437 */ + ngx_null_string, /* 438 */ + ngx_null_string, /* 439 */ + ngx_null_string, /* 440 */ + ngx_null_string, /* 441 */ + ngx_null_string, /* 442 */ + ngx_null_string, /* 443 */ + ngx_null_string, /* 444 */ + ngx_null_string, /* 445 */ + ngx_null_string, /* 446 */ + ngx_null_string, /* 447 */ + ngx_null_string, /* 448 */ + ngx_null_string, /* 449 */ + ngx_null_string, /* 450 */ + ngx_string(ngx_http_error_451_page), /* 451, Unavailable For Legal Reasons */ -#define NGX_HTTP_LAST_4XX 422 +#define NGX_HTTP_LAST_4XX 452 #define NGX_HTTP_OFF_5XX (NGX_HTTP_LAST_4XX - 400 + NGX_HTTP_OFF_4XX) ngx_string(ngx_http_error_494_page), /* 494, request header too large */ [1] https://datatracker.ietf.org/doc/rfc7725/?include_text=1 [2] http://www.iana.org/assignments/link-relations/link-relations.xhtml Kind Regards, -- Babak Farrokhi https://github.com/farrokhi
signature.asc
Description: OpenPGP digital signature
_______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel