nginx-0.0.3-2004-04-14-09:57:36 import
diff --git a/src/core/nginx.c b/src/core/nginx.c
index da03b7d..56a8914 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -85,10 +85,6 @@
ngx_cycle_t *cycle, init_cycle;
ngx_core_conf_t *ccf;
ngx_master_ctx_t ctx;
-#if !(WIN32)
- size_t len;
- u_char pid[/* STUB */ 10];
-#endif
#if __FreeBSD__
ngx_debug_init();
@@ -111,10 +107,6 @@
init_cycle.log = log;
ngx_cycle = &init_cycle;
-#if 0
- /* STUB */ log->log_level = NGX_LOG_DEBUG_ALL;
-#endif
-
ngx_memzero(&ctx, sizeof(ngx_master_ctx_t));
ctx.argc = argc;
ctx.argv = argv;
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index 76a665d..fc4c950 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -577,7 +577,7 @@
return "is duplicate";
}
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
if (ngx_strcasecmp(value[1].data, "on") == 0) {
flag = 1;
@@ -611,7 +611,7 @@
return "is duplicate";
}
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
*field = value[1];
@@ -634,7 +634,7 @@
return "is duplicate";
}
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
*np = ngx_atoi(value[1].data, value[1].len);
if (*np == NGX_ERROR) {
return "invalid number";
@@ -663,7 +663,7 @@
return "is duplicate";
}
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
*sp = ngx_parse_size(&value[1]);
if (*sp == (size_t) NGX_ERROR) {
@@ -693,7 +693,7 @@
return "is duplicate";
}
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
*msp = ngx_parse_time(&value[1], 0);
if (*msp == (ngx_msec_t) NGX_ERROR) {
@@ -727,7 +727,7 @@
return "is duplicate";
}
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
*sp = ngx_parse_time(&value[1], 1);
if (*sp == NGX_ERROR) {
@@ -760,7 +760,7 @@
return "is duplicate";
}
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
bufs->num = ngx_atoi(value[1].data, value[1].len);
if (bufs->num == NGX_ERROR || bufs->num == 0) {
@@ -776,6 +776,42 @@
}
+char *ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ char *p = conf;
+
+ ngx_uint_t *np, i;
+ ngx_str_t *value;
+ ngx_conf_enum_t *e;
+
+ np = (ngx_uint_t *) (p + cmd->offset);
+
+ if (*np != NGX_CONF_UNSET_UINT) {
+ return "is duplicate";
+ }
+
+ value = cf->args->elts;
+ e = cmd->post;
+
+ for (i = 0; e[i].name.len != 0; i++) {
+ if (e[i].name.len != value[1].len
+ || ngx_strcasecmp(e[i].name.data, value[1].data) != 0)
+ {
+ continue;
+ }
+
+ *np = e[i].value;
+
+ return NGX_CONF_OK;
+ }
+
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "invalid value \"%s\"", value[1].data);
+
+ return NGX_CONF_ERROR;
+}
+
+
char *ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
char *p = conf;
@@ -786,14 +822,14 @@
np = (ngx_uint_t *) (p + cmd->offset);
- value = (ngx_str_t *) cf->args->elts;
+ value = cf->args->elts;
mask = cmd->post;
for (i = 1; i < cf->args->nelts; i++) {
for (m = 0; mask[m].name.len != 0; m++) {
if (mask[m].name.len != value[i].len
- && ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
+ || ngx_strcasecmp(mask[m].name.data, value[i].data) != 0)
{
continue;
}
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index dc4eb7a..353e098 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -42,6 +42,7 @@
#define NGX_CONF_UNSET -1
+#define NGX_CONF_UNSET_UINT (ngx_uint_t) -1
#define NGX_CONF_UNSET_SIZE (size_t) -1
#define NGX_CONF_UNSET_MSEC (ngx_msec_t) -1
@@ -151,11 +152,17 @@
} ngx_conf_num_bounds_t;
+typedef struct {
+ ngx_str_t name;
+ ngx_uint_t value;
+} ngx_conf_enum_t;
+
+
#define NGX_CONF_BITMASK_SET 1
typedef struct {
- ngx_str_t name;
- int mask;
+ ngx_str_t name;
+ ngx_uint_t mask;
} ngx_conf_bitmask_t;
@@ -196,6 +203,11 @@
conf = (prev == NGX_CONF_UNSET) ? default : prev; \
}
+#define ngx_conf_merge_unsigned_value(conf, prev, default) \
+ if (conf == NGX_CONF_UNSET_UINT) { \
+ conf = (prev == NGX_CONF_UNSET_UINT) ? default : prev; \
+ }
+
#define ngx_conf_merge_msec_value(conf, prev, default) \
if (conf == NGX_CONF_UNSET_MSEC) { \
conf = (prev == NGX_CONF_UNSET_MSEC) ? default : prev; \
@@ -258,6 +270,7 @@
char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_time_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_conf_set_enum_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
char *ngx_conf_set_bitmask_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c
index 67c2dc0..dd98eca 100644
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -66,7 +66,8 @@
nevents = 0;
}
- if (cycle->old_cycle == NULL
+ if (ngx_process == NGX_PROCESS_WORKER
+ || cycle->old_cycle == NULL
|| cycle->old_cycle->connection_n < cycle->connection_n)
{
ngx_test_null(list,
@@ -393,7 +394,8 @@
if (event_list[i].fd == -1) {
/*
- * the disabled event, a workaround for our possible bug, see below
+ * the disabled event, a workaround for our possible bug,
+ * see the comment below
*/
continue;
}
diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c
index 7fc79ba..596ee6a 100644
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -9,6 +9,7 @@
#include <ngx_event.h>
+
static int ngx_select_init(ngx_cycle_t *cycle);
static void ngx_select_done(ngx_cycle_t *cycle);
static int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags);
@@ -30,10 +31,14 @@
static int max_fd;
#endif
-static int nevents;
+static ngx_uint_t nevents;
static ngx_event_t **event_index;
+#if 0
static ngx_event_t **ready_index;
+#endif
+
+static ngx_event_t *accept_events;
static ngx_str_t select_name = ngx_string("select");
@@ -77,7 +82,8 @@
nevents = 0;
}
- if (cycle->old_cycle == NULL
+ if (ngx_process == NGX_PROCESS_WORKER
+ || cycle->old_cycle == NULL
|| cycle->old_cycle->connection_n < cycle->connection_n)
{
ngx_test_null(index,
@@ -91,6 +97,7 @@
}
event_index = index;
+#if 0
if (ready_index) {
ngx_free(ready_index);
}
@@ -98,6 +105,7 @@
ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
cycle->log),
NGX_ERROR);
+#endif
}
ngx_io = ngx_os_io;
@@ -119,7 +127,9 @@
static void ngx_select_done(ngx_cycle_t *cycle)
{
ngx_free(event_index);
+#if 0
ngx_free(ready_index);
+#endif
event_index = NULL;
}
@@ -192,6 +202,9 @@
c = ev->data;
+ ev->active = 0;
+ ev->posted = 0;
+
if (ev->index == NGX_INVALID_INDEX) {
return NGX_OK;
}
@@ -230,7 +243,6 @@
event_index[ev->index]->index = ev->index;
}
- ev->active = 0;
ev->index = NGX_INVALID_INDEX;
return NGX_OK;
@@ -239,15 +251,16 @@
static int ngx_select_process_events(ngx_cycle_t *cycle)
{
- int i, ready, nready,found;
- ngx_err_t err;
- ngx_msec_t timer;
- ngx_event_t *ev;
- ngx_connection_t *c;
- ngx_epoch_msec_t delta;
- struct timeval tv, *tp;
+ int ready, nready;
+ ngx_uint_t i, found, lock, expire;
+ ngx_err_t err;
+ ngx_msec_t timer;
+ ngx_event_t *ev;
+ ngx_connection_t *c;
+ ngx_epoch_msec_t delta;
+ struct timeval tv, *tp;
#if (HAVE_SELECT_CHANGE_TIMEOUT)
- static ngx_epoch_msec_t deltas = 0;
+ static ngx_epoch_msec_t deltas = 0;
#endif
work_read_fd_set = master_read_fd_set;
@@ -260,12 +273,24 @@
tv.tv_sec = timer / 1000;
tv.tv_usec = (timer % 1000) * 1000;
tp = &tv;
+ expire = 1;
} else {
tp = NULL;
+ expire = 0;
}
+#if (NGX_DEBUG)
+ for (i = 0; i < nevents; i++) {
+ ev = event_index[i];
+ c = ev->data;
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+ "select event: fd:%d wr:%d", c->fd,ev->write);
+ }
+#endif
+
#if !(WIN32)
+
if (max_fd == -1) {
for (i = 0; i < nevents; i++) {
c = event_index[i]->data;
@@ -277,15 +302,18 @@
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"change max_fd: %d", max_fd);
}
-#endif
-#if (NGX_DEBUG)
- for (i = 0; i < nevents; i++) {
- ev = event_index[i];
- c = ev->data;
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- "select event: fd:%d wr:%d", c->fd,ev->write);
+ if (ngx_accept_mutex) {
+ if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_accept_mutex_held == 0 && timer > ngx_accept_mutex_delay) {
+ timer = ngx_accept_mutex_delay;
+ expire = 0;
+ }
}
+
#endif
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
@@ -372,6 +400,13 @@
return NGX_ERROR;
}
+
+ if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
+ ngx_accept_mutex_unlock();
+ return NGX_ERROR;
+ }
+
+ lock = 1;
nready = 0;
for (i = 0; i < nevents; i++) {
@@ -395,10 +430,36 @@
}
if (found) {
+ ev->ready = 1;
+
+ if (ev->oneshot) {
+ if (ev->timer_set) {
+ ngx_del_timer(ev);
+ }
+
+ if (ev->write) {
+ ngx_select_del_event(ev, NGX_WRITE_EVENT, 0);
+ } else {
+ ngx_select_del_event(ev, NGX_READ_EVENT, 0);
+ }
+ }
+
+ if (ev->accept) {
+ ev->next = accept_events;
+ accept_events = ev;
+ } else {
+ ngx_post_event(ev);
+ }
+
+ nready++;
+
+#if 0
ready_index[nready++] = ev;
+#endif
}
}
+#if 0
for (i = 0; i < nready; i++) {
ev = ready_index[i];
ready--;
@@ -423,15 +484,56 @@
ev->event_handler(ev);
}
+#endif
- if (ready != 0) {
+ ev = accept_events;
+
+ for ( ;; ) {
+
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+ "accept event " PTR_FMT, ev);
+
+ if (ev == NULL) {
+ break;
+ }
+
+ ngx_mutex_unlock(ngx_posted_events_mutex);
+
+ ev->event_handler(ev);
+
+ ev = ev->next;
+
+ if (ev == NULL) {
+ lock = 0;
+ break;
+ }
+
+ if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
+ ngx_accept_mutex_unlock();
+ return NGX_ERROR;
+ }
+
+ }
+
+ if (lock) {
+ ngx_mutex_unlock(ngx_posted_events_mutex);
+ }
+
+ ngx_accept_mutex_unlock();
+ accept_events = NULL;
+
+ if (ready != nready) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events");
}
- if (timer && delta) {
+ if (expire && delta) {
ngx_event_expire_timers((ngx_msec_t) delta);
}
+ if (!ngx_threaded) {
+ ngx_event_process_posted(cycle);
+ }
+
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c
index a1640bd..c62a9ea 100644
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -12,12 +12,23 @@
ngx_bufs_t bufs;
+ ngx_uint_t http_version;
+ ngx_uint_t proxied;
+
int level;
int wbits;
int memlevel;
} ngx_http_gzip_conf_t;
+enum {
+ NGX_HTTP_GZIP_PROXIED_OFF = 0,
+ NGX_HTTP_GZIP_PROXIED_NOCACHABLE,
+ NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE,
+ NGX_HTTP_GZIP_PROXIED_ON
+};
+
+
typedef struct {
ngx_chain_t *in;
ngx_chain_t *free;
@@ -76,6 +87,24 @@
+static ngx_conf_enum_t ngx_http_gzip_http_version[] = {
+ { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
+ { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
+ { ngx_null_string, 0 }
+};
+
+
+static ngx_conf_enum_t ngx_http_gzip_proxied[] = {
+ { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
+#if 0
+ { ngx_string("nocachable"), NGX_HTTP_GZIP_PROXIED_NOCACHABLE },
+ { ngx_string("poor_cachable"), NGX_HTTP_GZIP_PROXIED_POOR_CACHABLE },
+#endif
+ { ngx_string("on"), NGX_HTTP_GZIP_PROXIED_ON },
+ { ngx_null_string, 0 }
+};
+
+
static ngx_command_t ngx_http_gzip_filter_commands[] = {
{ ngx_string("gzip"),
@@ -120,6 +149,20 @@
offsetof(ngx_http_gzip_conf_t, no_buffer),
NULL},
+ { ngx_string("gzip_http_version"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
+ ngx_conf_set_enum_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_gzip_conf_t, http_version),
+ &ngx_http_gzip_http_version },
+
+ { ngx_string("gzip_proxied"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
+ ngx_conf_set_enum_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_gzip_conf_t, proxied),
+ &ngx_http_gzip_proxied },
+
ngx_null_command
};
@@ -188,7 +231,7 @@
if (!conf->enable
|| r->headers_out.status != NGX_HTTP_OK
|| r->header_only
- /* TODO: conf->http_version */
+ || r->http_version < conf->http_version
|| (r->headers_out.content_encoding
&& r->headers_out.content_encoding->value.len)
|| r->headers_in.accept_encoding == NULL
@@ -206,6 +249,27 @@
return ngx_http_next_header_filter(r);
}
+
+ /* TODO: proxied */
+ if (r->headers_in.via && conf->proxied == NGX_HTTP_GZIP_PROXIED_OFF) {
+ return ngx_http_next_header_filter(r);
+ }
+
+
+ /*
+ * if the URL (without the "http://" prefix) is longer than 253 bytes
+ * then MSIE 4.x can not handle the compressed stream - it waits too long,
+ * hangs up or crashes
+ */
+
+ if (r->headers_in.user_agent
+ && r->unparsed_uri.len > 200
+ && ngx_strstr(r->headers_in.user_agent->value.data, "MSIE 4"))
+ {
+ return ngx_http_next_header_filter(r);
+ }
+
+
ngx_http_create_ctx(r, ctx, ngx_http_gzip_filter_module,
sizeof(ngx_http_gzip_ctx_t), NGX_ERROR);
ctx->request = r;
@@ -654,6 +718,9 @@
/* conf->bufs.num = 0; */
+ conf->http_version = NGX_CONF_UNSET_UINT;
+ conf->proxied = NGX_CONF_UNSET_UINT;
+
conf->level = NGX_CONF_UNSET;
conf->wbits = NGX_CONF_UNSET;
conf->memlevel = NGX_CONF_UNSET;
@@ -669,8 +736,15 @@
ngx_http_gzip_conf_t *conf = child;
ngx_conf_merge_value(conf->enable, prev->enable, 0);
+
ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4,
/* STUB: PAGE_SIZE */ 4096);
+
+ ngx_conf_merge_unsigned_value(conf->http_version, prev->http_version,
+ NGX_HTTP_VERSION_11);
+ ngx_conf_merge_unsigned_value(conf->proxied, prev->proxied,
+ NGX_HTTP_GZIP_PROXIED_OFF);
+
ngx_conf_merge_value(conf->level, prev->level, 1);
ngx_conf_merge_value(conf->wbits, prev->wbits, MAX_WBITS);
ngx_conf_merge_value(conf->memlevel, prev->memlevel, MAX_MEM_LEVEL - 1);
diff --git a/src/http/modules/ngx_http_range_filter.c b/src/http/modules/ngx_http_range_filter.c
index 5bf4be0..df32acf 100644
--- a/src/http/modules/ngx_http_range_filter.c
+++ b/src/http/modules/ngx_http_range_filter.c
@@ -91,7 +91,10 @@
/* STUB: we currently support ranges for file hunks only */
|| !r->sendfile
- || r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY)
+ || r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY
+
+ || (r->headers_out.content_encoding
+ && r->headers_out.content_encoding->value.len))
{
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index 760d8d6..41946bf 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -117,13 +117,19 @@
r = p->request;
uc = p->lcf->upstream;
- len = http_methods[p->upstream->method - 1].len
- + uc->uri.len
- + r->uri.len - uc->location->len
- + 1 + r->args.len /* 1 is for "?" */
- + sizeof(http_version) - 1
- + sizeof(connection_close_header) - 1
- + 2; /* 2 is for "\r\n" at the header end */
+ if (p->upstream->method) {
+ len = http_methods[p->upstream->method - 1].len;
+
+ } else {
+ len = r->method_name.len;
+ }
+
+ len += uc->uri.len
+ + r->uri.len - uc->location->len
+ + 1 + r->args.len /* 1 is for "?" */
+ + sizeof(http_version) - 1
+ + sizeof(connection_close_header) - 1
+ + 2; /* 2 is for "\r\n" at the header end */
if (p->lcf->preserve_host && r->headers_in.host) {
@@ -179,8 +185,13 @@
/* the request line */
- h->last = ngx_cpymem(h->last, http_methods[p->upstream->method - 1].data,
- http_methods[p->upstream->method - 1].len);
+ if (p->upstream->method) {
+ h->last = ngx_cpymem(h->last,
+ http_methods[p->upstream->method - 1].data,
+ http_methods[p->upstream->method - 1].len);
+ } else {
+ h->last = ngx_cpymem(h->last, r->method_name.data, r->method_name.len);
+ }
h->last = ngx_cpymem(h->last, uc->uri.data, uc->uri.len);
diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c
index e1304e8..33bc237 100644
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -5,19 +5,17 @@
ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r)
{
- u_char ch, *p;
+ u_char ch, *p, *m;
enum {
sw_start = 0,
- sw_G,
- sw_GE,
- sw_H,
- sw_HE,
- sw_HEA,
- sw_P,
- sw_PO,
- sw_POS,
+ sw_method,
sw_space_after_method,
sw_spaces_before_uri,
+ sw_schema,
+ sw_schema_slash,
+ sw_schema_slash_slash,
+ sw_host,
+ sw_port,
sw_after_slash_in_uri,
sw_check_uri,
sw_uri,
@@ -48,102 +46,46 @@
case sw_start:
r->request_start = p - 1;
- switch (ch) {
- case 'G':
- state = sw_G;
- break;
- case 'H':
- state = sw_H;
- break;
- case 'P':
- state = sw_P;
- break;
- default:
+ if (ch < 'A' || ch > 'Z') {
return NGX_HTTP_PARSE_INVALID_METHOD;
}
+
+ state = sw_method;
break;
- case sw_G:
- switch (ch) {
- case 'E':
- state = sw_GE;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
- break;
+ case sw_method:
+ if (ch == ' ') {
+ r->method_end = p - 1;
+ m = r->request_start;
- case sw_GE:
- switch (ch) {
- case 'T':
- r->method = NGX_HTTP_GET;
- state = sw_space_after_method;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
- break;
+ if (r->method_end - m == 3) {
- case sw_H:
- switch (ch) {
- case 'E':
- state = sw_HE;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
- break;
+ if (*m == 'G' && *(m + 1) == 'E' && *(m + 2) == 'T') {
+ r->method = NGX_HTTP_GET;
+ }
- case sw_HE:
- switch (ch) {
- case 'A':
- state = sw_HEA;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
- break;
+ } else if (r->method_end - m == 4) {
- case sw_HEA:
- switch (ch) {
- case 'D':
- r->method = NGX_HTTP_HEAD;
- state = sw_space_after_method;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
- break;
+ if (*m == 'P' && *(m + 1) == 'O'
+ && *(m + 2) == 'T' && *(m + 3) == 'T')
+ {
+ r->method = NGX_HTTP_POST;
- case sw_P:
- switch (ch) {
- case 'O':
- state = sw_PO;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
- break;
+ } else if (*m == 'H' && *(m + 1) == 'E'
+ && *(m + 2) == 'A' && *(m + 3) == 'D')
+ {
+ r->method = NGX_HTTP_HEAD;
+ }
+ }
- case sw_PO:
- switch (ch) {
- case 'S':
- state = sw_POS;
+ state = sw_spaces_before_uri;
break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
}
- break;
- case sw_POS:
- switch (ch) {
- case 'T':
- r->method = NGX_HTTP_POST;
- state = sw_space_after_method;
- break;
- default:
+ if (ch < 'A' || ch > 'Z') {
return NGX_HTTP_PARSE_INVALID_METHOD;
}
+
break;
/* single space after method */
@@ -167,9 +109,82 @@
case ' ':
break;
default:
- r->unusual_uri = 1;
+ if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+ r->schema_start = p - 1;
+ state = sw_schema;
+ break;
+ }
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ break;
+
+ case sw_schema:
+ switch (ch) {
+ case ':':
+ r->schema_end = p - 1;
+ state = sw_schema_slash;
+ break;
+ default:
+ if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {
+ break;
+ }
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ break;
+
+ case sw_schema_slash:
+ switch (ch) {
+ case '/':
+ state = sw_schema_slash_slash;
+ break;
+ default:
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ break;
+
+ case sw_schema_slash_slash:
+ switch (ch) {
+ case '/':
+ r->host_start = p - 1;
+ state = sw_host;
+ break;
+ default:
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ break;
+
+ case sw_host:
+ switch (ch) {
+ case ':':
+ r->host_end = p - 1;
+ state = sw_port;
+ break;
+ case '/':
+ r->host_end = p - 1;
r->uri_start = p - 1;
- state = sw_uri;
+ state = sw_after_slash_in_uri;
+ break;
+ default:
+ if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')
+ || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-')
+ {
+ break;
+ }
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
+ break;
+
+ case sw_port:
+ switch (ch) {
+ case '/':
+ r->port_end = p - 1;
+ r->uri_start = p - 1;
+ state = sw_after_slash_in_uri;
+ break;
+ default:
+ if (ch < '0' && ch > '9') {
+ return NGX_HTTP_PARSE_INVALID_REQUEST;
+ }
break;
}
break;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 976475e..30b3e59 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -337,6 +337,7 @@
/* the request line has been parsed successfully */
+#if 0
/* TODO: we need to handle proxy URIs */
if (r->unusual_uri) {
r->request_line.len = r->request_end - r->request_start;
@@ -349,6 +350,7 @@
NGX_HTTP_BAD_REQUEST);
return;
}
+#endif
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
@@ -438,6 +440,10 @@
r->request_line.data[r->request_line.len] = '\0';
}
+ if (r->method == 0) {
+ r->method_name.len = r->method_end - r->request_start + 1;
+ r->method_name.data = r->request_line.data;
+ }
if (r->uri_ext) {
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 215dedf..e5ae3e1 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -223,6 +223,8 @@
ngx_str_t exten;
ngx_str_t unparsed_uri;
+ ngx_str_t method_name;
+
ngx_http_request_t *main;
uint32_t in_addr;
@@ -246,8 +248,10 @@
unsigned http_state:4;
+#if 0
/* URI is not started with '/' - "GET http://" */
unsigned unusual_uri:1;
+#endif
/* URI with "/.", "%" and on Win32 with "//" */
unsigned complex_uri:1;
unsigned header_timeout_set:1;
@@ -281,6 +285,13 @@
u_char *args_start;
u_char *request_start;
u_char *request_end;
+ u_char *method_end;
+ u_char *schema_start;
+ u_char *schema_end;
+ u_char *host_start;
+ u_char *host_end;
+ u_char *port_start;
+ u_char *port_end;
u_char *header_name_start;
u_char *header_name_end;
u_char *header_start;