

![]() | Start a set with this search |
![]() | Include this search in one of my sets |
![]() | Exclude this search from one of my sets |
![]() | Permalink to these results Paste this link in email or IM: |
| Atom feed for tracking future search results Paste this URL into your reader: |
6 messages in ru.sysoev.nginx[PATCH] "Allow" header| From | Sent On | Attachments |
|---|---|---|
| Evan Miller | May 19, 2007 2:00 pm | |
| Igor Sysoev | May 20, 2007 12:45 am | |
| Evan Miller | May 20, 2007 1:24 am | |
| Igor Sysoev | May 20, 2007 5:10 am | |
| Evan Miller | May 20, 2007 11:43 am | |
| Igor Sysoev | May 21, 2007 6:59 am |

![]() | Permalink for this message Paste this link in email or IM: |
![]() | Permalink for this thread Paste this link in email or IM: |
| Atom feed for this thread Paste this URL into your reader: |
| Subject: | [PATCH] "Allow" header | Actions... |
|---|---|---|
| From: | Evan Miller (emmi...@public.gmane.org) | |
| Date: | May 19, 2007 2:00:05 pm | |
| List: | ru.sysoev.nginx | |
The "Allow" header in HTTP tells a client what methods (GET, POST, DELETE, etc.) are permitted at a certain URL. RFC 2616 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7) says that an HTTP 1.1 server "MUST" return an Allow header with all 405 Method Not Allowed responses. However, Nginx does not currently comply with this provision. Below is a patch to support the Allow header. It puts the burden of defining legal methods on handler modules, so I have modified all of the modules that return a 405 response to use the Allow header appropriately.
Without patch:
DELETE /static/foo.bar HTTP/1.1 Host: tim
HTTP/1.1 405 Not Allowed Server: nginx/0.5.20 Date: Sat, 19 May 2007 20:22:06 GMT Content-Type: text/html Content-Length: 173
<snip>
With patch:
DELETE /static/foo.bar HTTP/1.1 Host: tim
HTTP/1.1 405 Not Allowed Server: nginx/0.5.20 Date: Sat, 19 May 2007 20:22:06 GMT Content-Type: text/html Content-Length: 173 Allow: GET, HEAD
<snip>
The patch works by letting modules set r->headers_out.allow_methods to a bitwise OR'd representation of the methods they allow. Modules can also set the Allow header explicitly and store the resulting ngx_table_elt_t in r->headers_out.allow, in which case the bitwise representation will be ignored. This follows the pattern of the other headers.
Comments appreciated.
Evan
diff -Naur nginx-0.5.20/src/http/modules/ngx_http_empty_gif_module.c nginx-evanm-0.5.20/src/http/modules/ngx_http_empty_gif_module.c --- nginx-0.5.20/src/http/modules/ngx_http_empty_gif_module.c 2007-01-17 02:50:52.000000000 -0800 +++ nginx-evanm-0.5.20/src/http/modules/ngx_http_empty_gif_module.c 2007-05-19 13:01:05.000000000 -0700 @@ -113,6 +113,7 @@ ngx_chain_t out;
if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { + r->headers_out.allow_methods = NGX_HTTP_GET|NGX_HTTP_HEAD; return NGX_HTTP_NOT_ALLOWED; }
diff -Naur nginx-0.5.20/src/http/modules/ngx_http_flv_module.c nginx-evanm-0.5.20/src/http/modules/ngx_http_flv_module.c --- nginx-0.5.20/src/http/modules/ngx_http_flv_module.c 2007-01-18 12:15:09.000000000 -0800 +++ nginx-evanm-0.5.20/src/http/modules/ngx_http_flv_module.c 2007-05-19 13:01:32.000000000 -0700 @@ -77,6 +77,7 @@ ngx_http_core_loc_conf_t *clcf;
if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { + r->headers_out.allow_methods = NGX_HTTP_GET|NGX_HTTP_HEAD; return NGX_HTTP_NOT_ALLOWED; }
diff -Naur nginx-0.5.20/src/http/modules/ngx_http_memcached_module.c nginx-evanm-0.5.20/src/http/modules/ngx_http_memcached_module.c --- nginx-0.5.20/src/http/modules/ngx_http_memcached_module.c 2007-01-29 03:54:36.000000000 -0800 +++ nginx-evanm-0.5.20/src/http/modules/ngx_http_memcached_module.c 2007-05-19 13:02:10.000000000 -0700 @@ -164,6 +164,7 @@ ngx_http_memcached_loc_conf_t *mlcf;
if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { + r->headers_out.allow_methods = NGX_HTTP_GET|NGX_HTTP_HEAD; return NGX_HTTP_NOT_ALLOWED; }
diff -Naur nginx-0.5.20/src/http/modules/ngx_http_static_module.c nginx-evanm-0.5.20/src/http/modules/ngx_http_static_module.c --- nginx-0.5.20/src/http/modules/ngx_http_static_module.c 2007-01-18 12:15:09.000000000 -0800 +++ nginx-evanm-0.5.20/src/http/modules/ngx_http_static_module.c 2007-05-19 13:02:43.000000000 -0700 @@ -88,6 +88,7 @@ ngx_http_core_loc_conf_t *clcf;
if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { + r->headers_out.allow_methods = NGX_HTTP_GET|NGX_HTTP_HEAD; return NGX_HTTP_NOT_ALLOWED; }
diff -Naur nginx-0.5.20/src/http/modules/ngx_http_stub_status_module.c nginx-evanm-0.5.20/src/http/modules/ngx_http_stub_status_module.c --- nginx-0.5.20/src/http/modules/ngx_http_stub_status_module.c 2006-08-30 03:39:17.000000000 -0700 +++ nginx-evanm-0.5.20/src/http/modules/ngx_http_stub_status_module.c 2007-05-19 13:03:35.000000000 -0700 @@ -65,7 +65,8 @@ ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr;
- if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { + r->headers_out.allow_methods = NGX_HTTP_GET|NGX_HTTP_HEAD; return NGX_HTTP_NOT_ALLOWED; }
diff -Naur nginx-0.5.20/src/http/ngx_http_header_filter_module.c nginx-evanm-0.5.20/src/http/ngx_http_header_filter_module.c --- nginx-0.5.20/src/http/ngx_http_header_filter_module.c 2007-01-18 12:51:51.000000000 -0800 +++ nginx-evanm-0.5.20/src/http/ngx_http_header_filter_module.c 2007-05-19 13:55:02.000000000 -0700 @@ -121,6 +121,25 @@ /* ngx_null_string, */ /* "510 Not Extended" */ };
+static ngx_str_t ngx_http_methods[] = { + ngx_string("UNKNOWN"), + ngx_string("GET"), + ngx_string("HEAD"), + ngx_string("POST"), + ngx_string("PUT"), + ngx_string("DELETE"), + ngx_string("MKCOL"), + ngx_string("COPY"), + ngx_string("MOVE"), + ngx_string("OPTIONS"), + ngx_string("PROPFIND"), + ngx_string("PROPPATCH"), + ngx_string("LOCK"), + ngx_string("UNLOCK"), + ngx_string("TRACE"), + ngx_null_string, + }; +
ngx_http_header_out_t ngx_http_headers_out[] = { { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) }, @@ -153,7 +172,7 @@ u_char *p; size_t len; ngx_buf_t *b; - ngx_uint_t status, i; + ngx_uint_t status, i, allow_methods_n; ngx_chain_t out; ngx_list_part_t *part; ngx_table_elt_t *header; @@ -268,6 +287,24 @@ len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; }
+ allow_methods_n = 0; + + if (r->headers_out.allow == NULL + && r->headers_out.allow_methods) + { + for (i=0; ngx_http_methods[i].len; i++) { + if (r->headers_out.allow_methods & (1 << i)) { + allow_methods_n++; + len += ngx_http_methods[i].len; + } + } + if (allow_methods_n) { + len += sizeof("Allow: ") - 1; + len += 2 * (allow_methods_n - 1); // commas and spaces + len += sizeof(CRLF) - 1; + } + } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (r->headers_out.location @@ -418,6 +455,23 @@ *b->last++ = CR; *b->last++ = LF; }
+ if (r->headers_out.allow == NULL + && allow_methods_n) + { + b->last = ngx_cpymem(b->last, "Allow: ", + sizeof("Allow: ") - 1); + for (i=0; ngx_http_methods[i].len; i++) { + if (r->headers_out.allow_methods & (1 << i)) { + b->last = ngx_copy(b->last, ngx_http_methods[i].data, + ngx_http_methods[i].len); + if (--allow_methods_n) { + *b->last++ = ','; *b->last++ = ' '; + } + } + } + *b->last++ = CR; *b->last++ = LF; + } + if (r->headers_out.location && r->headers_out.location->value.len && r->headers_out.location->value.data[0] == '/') diff -Naur nginx-0.5.20/src/http/ngx_http_request.h nginx-evanm-0.5.20/src/http/ngx_http_request.h --- nginx-0.5.20/src/http/ngx_http_request.h 2007-04-21 00:50:19.000000000 -0700 +++ nginx-evanm-0.5.20/src/http/ngx_http_request.h 2007-05-19 13:14:35.000000000 -0700 @@ -230,6 +230,7 @@ ngx_table_elt_t *content_encoding; ngx_table_elt_t *location; ngx_table_elt_t *last_modified; + ngx_table_elt_t *allow; ngx_table_elt_t *content_range; ngx_table_elt_t *accept_ranges; ngx_table_elt_t *www_authenticate; @@ -247,6 +248,8 @@ off_t content_length_n; time_t date_time; time_t last_modified_time; + + ngx_uint_t allow_methods; } ngx_http_headers_out_t;







