Skip to content

Instantly share code, notes, and snippets.

@pointcom
Created January 15, 2009 17:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pointcom/47503 to your computer and use it in GitHub Desktop.
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)
--- 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