# HG changeset patch # User Igor Sysoev # Date 1081922256 0 # Node ID d71c87d11b16c47df6797daffd393ad6b137e15e # Parent 98f1a8028067ccc7cd7d63e49351d954ffb0cd30 nginx-0.0.3-2004-04-14-09:57:36 import diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -85,10 +85,6 @@ int main(int argc, char *const *argv) 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 @@ int main(int argc, char *const *argv) 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 --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -577,7 +577,7 @@ char *ngx_conf_set_flag_slot(ngx_conf_t 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 @@ char *ngx_conf_set_str_slot(ngx_conf_t * return "is duplicate"; } - value = (ngx_str_t *) cf->args->elts; + value = cf->args->elts; *field = value[1]; @@ -634,7 +634,7 @@ char *ngx_conf_set_num_slot(ngx_conf_t * 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 @@ char *ngx_conf_set_size_slot(ngx_conf_t 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 @@ char *ngx_conf_set_msec_slot(ngx_conf_t 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 @@ char *ngx_conf_set_sec_slot(ngx_conf_t * 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 @@ char *ngx_conf_set_bufs_slot(ngx_conf_t 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_bufs_slot(ngx_conf_t } +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 @@ char *ngx_conf_set_bitmask_slot(ngx_conf 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 --- 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 @@ typedef struct { } 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 @@ char *ngx_conf_check_num_bounds(ngx_conf 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_msec_slot(ngx_conf_t 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 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -66,7 +66,8 @@ static int ngx_poll_init(ngx_cycle_t *cy 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 @@ int ngx_poll_process_events(ngx_cycle_t 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 --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -9,6 +9,7 @@ #include + 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_write; 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 @@ static int ngx_select_init(ngx_cycle_t * 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 @@ static int ngx_select_init(ngx_cycle_t * } event_index = index; +#if 0 if (ready_index) { ngx_free(ready_index); } @@ -98,6 +105,7 @@ static int ngx_select_init(ngx_cycle_t * 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 int ngx_select_init(ngx_cycle_t * 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 @@ static int ngx_select_del_event(ngx_even c = ev->data; + ev->active = 0; + ev->posted = 0; + if (ev->index == NGX_INVALID_INDEX) { return NGX_OK; } @@ -230,7 +243,6 @@ static int ngx_select_del_event(ngx_even 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_del_event(ngx_even 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 @@ static int ngx_select_process_events(ngx 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 @@ static int ngx_select_process_events(ngx ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "change max_fd: %d", max_fd); } -#endif + + if (ngx_accept_mutex) { + if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { + return NGX_ERROR; + } -#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_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 @@ static int ngx_select_process_events(ngx 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 @@ static int ngx_select_process_events(ngx } 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 @@ static int ngx_select_process_events(ngx 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 --- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c @@ -12,12 +12,23 @@ typedef struct { 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_post_handler_pt ngx_htt +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 @@ static ngx_command_t ngx_http_gzip_filt 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 @@ static int ngx_http_gzip_header_filter(n 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 @@ static int ngx_http_gzip_header_filter(n 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 @@ static void *ngx_http_gzip_create_conf(n /* 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 @@ static char *ngx_http_gzip_merge_conf(ng 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 --- a/src/http/modules/ngx_http_range_filter.c +++ b/src/http/modules/ngx_http_range_filter.c @@ -91,7 +91,10 @@ static ngx_int_t ngx_http_range_header_f /* 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 --- a/src/http/modules/proxy/ngx_http_proxy_upstream.c +++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c @@ -117,13 +117,19 @@ static ngx_chain_t *ngx_http_proxy_creat 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 @@ static ngx_chain_t *ngx_http_proxy_creat /* 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 --- 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 @@ ngx_int_t ngx_http_parse_request_line(ng 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; } - break; - case sw_G: - switch (ch) { - case 'E': - state = sw_GE; - break; - default: - return NGX_HTTP_PARSE_INVALID_METHOD; - } - break; - - 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; - - case sw_H: - switch (ch) { - case 'E': - state = sw_HE; - break; - default: - return NGX_HTTP_PARSE_INVALID_METHOD; - } + state = sw_method; break; - case sw_HE: - switch (ch) { - case 'A': - state = sw_HEA; + case sw_method: + if (ch == ' ') { + r->method_end = p - 1; + m = r->request_start; + + if (r->method_end - m == 3) { + + if (*m == 'G' && *(m + 1) == 'E' && *(m + 2) == 'T') { + r->method = NGX_HTTP_GET; + } + + } else if (r->method_end - m == 4) { + + if (*m == 'P' && *(m + 1) == 'O' + && *(m + 2) == 'T' && *(m + 3) == 'T') + { + r->method = NGX_HTTP_POST; + + } else if (*m == 'H' && *(m + 1) == 'E' + && *(m + 2) == 'A' && *(m + 3) == 'D') + { + r->method = NGX_HTTP_HEAD; + } + } + + state = sw_spaces_before_uri; break; - default: - return NGX_HTTP_PARSE_INVALID_METHOD; } - break; - case sw_HEA: - switch (ch) { - case 'D': - r->method = NGX_HTTP_HEAD; - state = sw_space_after_method; - break; - default: + if (ch < 'A' || ch > 'Z') { return NGX_HTTP_PARSE_INVALID_METHOD; } - break; - case sw_P: - switch (ch) { - case 'O': - state = sw_PO; - break; - default: - return NGX_HTTP_PARSE_INVALID_METHOD; - } - break; - - case sw_PO: - switch (ch) { - case 'S': - state = sw_POS; - 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: - return NGX_HTTP_PARSE_INVALID_METHOD; - } break; /* single space after method */ @@ -167,9 +109,82 @@ ngx_int_t ngx_http_parse_request_line(ng 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 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -337,6 +337,7 @@ static void ngx_http_process_request_lin /* 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 @@ static void ngx_http_process_request_lin NGX_HTTP_BAD_REQUEST); return; } +#endif cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); @@ -438,6 +440,10 @@ static void ngx_http_process_request_lin 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 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -223,6 +223,8 @@ struct ngx_http_request_s { 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 @@ struct ngx_http_request_s { 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 @@ struct ngx_http_request_s { 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;