Created
January 15, 2009 17:42
-
-
Save pointcom/47503 to your computer and use it in GitHub Desktop.
Patch for Nginx 0.6.34 : Added instruction "post_to_static" (HTTP 405 error when serving static file after a POST request)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- src/http/modules/ngx_http_static_module.c | |
+++ src/http/modules/ngx_http_static_module.c | |
@@ -9,10 +9,33 @@ | |
#include <ngx_http.h> | |
+typedef struct { | |
+ ngx_flag_t post_to_static; | |
+} ngx_http_static_loc_conf_t; | |
+ | |
+ | |
static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r); | |
+static void ngx_http_static_request(ngx_http_request_t *r); | |
+static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf); | |
+static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf, void *parent, | |
+ void *child); | |
static ngx_int_t ngx_http_static_init(ngx_conf_t *cf); | |
+static ngx_command_t ngx_http_static_commands[] = { | |
+ | |
+ { ngx_string("post_to_static"), | |
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF | |
+ |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, | |
+ ngx_conf_set_flag_slot, | |
+ NGX_HTTP_LOC_CONF_OFFSET, | |
+ offsetof(ngx_http_static_loc_conf_t, post_to_static), | |
+ NULL }, | |
+ | |
+ ngx_null_command | |
+}; | |
+ | |
+ | |
ngx_http_module_t ngx_http_static_module_ctx = { | |
NULL, /* preconfiguration */ | |
ngx_http_static_init, /* postconfiguration */ | |
@@ -23,15 +46,15 @@ ngx_http_module_t ngx_http_static_module_ctx = { | |
NULL, /* create server configuration */ | |
NULL, /* merge server configuration */ | |
- NULL, /* create location configuration */ | |
- NULL /* merge location configuration */ | |
+ ngx_http_static_create_loc_conf, /* create location configuration */ | |
+ ngx_http_static_merge_loc_conf /* merge location configuration */ | |
}; | |
ngx_module_t ngx_http_static_module = { | |
NGX_MODULE_V1, | |
&ngx_http_static_module_ctx, /* module context */ | |
- NULL, /* module directives */ | |
+ ngx_http_static_commands, /* module directives */ | |
NGX_HTTP_MODULE, /* module type */ | |
NULL, /* init master */ | |
NULL, /* init module */ | |
@@ -47,6 +70,52 @@ ngx_module_t ngx_http_static_module = { | |
static ngx_int_t | |
ngx_http_static_handler(ngx_http_request_t *r) | |
{ | |
+ ngx_int_t rc; | |
+ ngx_http_static_loc_conf_t *lcf; | |
+ | |
+ if (r->uri.data[r->uri.len - 1] == '/') { | |
+ return NGX_DECLINED; | |
+ } | |
+ | |
+ if (r->zero_in_uri) { | |
+ return NGX_DECLINED; | |
+ } | |
+ | |
+ if (r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD)) { | |
+ | |
+ rc = ngx_http_discard_request_body(r); | |
+ | |
+ if (rc != NGX_OK) { | |
+ return rc; | |
+ } | |
+ | |
+ ngx_http_static_request(r); | |
+ | |
+ return NGX_DONE; | |
+ | |
+ } else if (r->method & NGX_HTTP_POST) { | |
+ | |
+ lcf = ngx_http_get_module_loc_conf(r, ngx_http_static_module); | |
+ | |
+ if (lcf->post_to_static) { | |
+ | |
+ rc = ngx_http_read_client_request_body(r, ngx_http_static_request); | |
+ | |
+ if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
+ return rc; | |
+ } | |
+ | |
+ return NGX_DONE; | |
+ } | |
+ } | |
+ | |
+ return NGX_HTTP_NOT_ALLOWED; | |
+} | |
+ | |
+ | |
+static void | |
+ngx_http_static_request(ngx_http_request_t *r) | |
+{ | |
u_char *last, *location; | |
size_t root, len; | |
ngx_str_t path; | |
@@ -58,21 +127,6 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
ngx_open_file_info_t of; | |
ngx_http_core_loc_conf_t *clcf; | |
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) { | |
- return NGX_HTTP_NOT_ALLOWED; | |
- } | |
- | |
- if (r->uri.data[r->uri.len - 1] == '/') { | |
- return NGX_DECLINED; | |
- } | |
- | |
- /* TODO: Win32 */ | |
- if (r->zero_in_uri) { | |
- return NGX_DECLINED; | |
- } | |
- | |
- log = r->connection->log; | |
- | |
/* | |
* ngx_http_map_uri_to_path() allocates memory for terminating '\0' | |
* so we do not need to reserve memory for '/' for possible redirect | |
@@ -80,10 +134,13 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
last = ngx_http_map_uri_to_path(r, &path, &root, 0); | |
if (last == NULL) { | |
- return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
+ return; | |
} | |
path.len = last - path.data; | |
+ | |
+ log = r->connection->log; | |
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, | |
"http filename: \"%s\"", path.data); | |
@@ -102,7 +159,8 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
switch (of.err) { | |
case 0: | |
- return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
+ return; | |
case NGX_ENOENT: | |
case NGX_ENOTDIR: | |
@@ -130,7 +188,8 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
ngx_open_file_n " \"%s\" failed", path.data); | |
} | |
- return rc; | |
+ ngx_http_finalize_request(r, rc); | |
+ return; | |
} | |
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd); | |
@@ -141,7 +200,8 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); | |
if (r->headers_out.location == NULL) { | |
- return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
+ return; | |
} | |
len = r->uri.len + 1; | |
@@ -158,7 +218,8 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
location = ngx_palloc(r->pool, len); | |
if (location == NULL) { | |
- return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
+ return; | |
} | |
last = ngx_copy(location, r->uri.data, r->uri.len); | |
@@ -179,7 +240,8 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
r->headers_out.location->value.len = len; | |
r->headers_out.location->value.data = location; | |
- return NGX_HTTP_MOVED_PERMANENTLY; | |
+ ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY); | |
+ return; | |
} | |
#if !(NGX_WIN32) /* the not regular files are probably Unix specific */ | |
@@ -188,21 +250,12 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, | |
"\"%s\" is not a regular file", path.data); | |
- return NGX_HTTP_NOT_FOUND; | |
+ ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND); | |
+ return; | |
} | |
#endif | |
- if (r->method & NGX_HTTP_POST) { | |
- return NGX_HTTP_NOT_ALLOWED; | |
- } | |
- | |
- rc = ngx_http_discard_request_body(r); | |
- | |
- if (rc != NGX_OK) { | |
- return rc; | |
- } | |
- | |
log->action = "sending response to client"; | |
r->headers_out.status = NGX_HTTP_OK; | |
@@ -210,11 +263,13 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
r->headers_out.last_modified_time = of.mtime; | |
if (ngx_http_set_content_type(r) != NGX_OK) { | |
- return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
+ return; | |
} | |
if (r != r->main && of.size == 0) { | |
- return ngx_http_send_header(r); | |
+ ngx_http_finalize_request(r, ngx_http_send_header(r)); | |
+ return; | |
} | |
r->allow_ranges = 1; | |
@@ -223,18 +278,21 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); | |
if (b == NULL) { | |
- return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
+ return; | |
} | |
b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); | |
if (b->file == NULL) { | |
- return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
+ return; | |
} | |
rc = ngx_http_send_header(r); | |
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
- return rc; | |
+ ngx_http_finalize_request(r, rc); | |
+ return; | |
} | |
b->file_pos = 0; | |
@@ -251,7 +309,35 @@ ngx_http_static_handler(ngx_http_request_t *r) | |
out.buf = b; | |
out.next = NULL; | |
- return ngx_http_output_filter(r, &out); | |
+ ngx_http_finalize_request(r, ngx_http_output_filter(r, &out)); | |
+} | |
+ | |
+ | |
+static void * | |
+ngx_http_static_create_loc_conf(ngx_conf_t *cf) | |
+{ | |
+ ngx_http_static_loc_conf_t *lcf; | |
+ | |
+ lcf = ngx_palloc(cf->pool, sizeof(ngx_http_static_loc_conf_t)); | |
+ if (lcf == NULL) { | |
+ return NGX_CONF_ERROR; | |
+ } | |
+ | |
+ lcf->post_to_static = NGX_CONF_UNSET; | |
+ | |
+ return lcf; | |
+} | |
+ | |
+ | |
+static char * | |
+ngx_http_static_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
+{ | |
+ ngx_http_static_loc_conf_t *prev = parent; | |
+ ngx_http_static_loc_conf_t *conf = child; | |
+ | |
+ ngx_conf_merge_value(conf->post_to_static, prev->post_to_static, 0); | |
+ | |
+ return NGX_CONF_OK; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment