# HG changeset patch # User Igor Sysoev # Date 1052932393 0 # Node ID 674d333f42960c26c4c770d77d5bb1e49b1bc752 # Parent 5f6d848dcbef016f5eebf8fbc9ef64898aac8788 nginx-0.0.1-2003-05-14-21:13:13 import diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -52,6 +53,10 @@ int main(int argc, char *const *argv) /* STUB */ ngx_log.log_level = NGX_LOG_DEBUG; + if (ngx_os_init(&ngx_log) == NGX_ERROR) { + exit(1); + } + ngx_pool = ngx_create_pool(16 * 1024, &ngx_log); /* */ @@ -67,12 +72,6 @@ int main(int argc, char *const *argv) #endif -#if 0 - if (ngx_os_init(&ngx_log) == NGX_ERROR) { - exit(1); - } -#endif - ngx_init_array(ngx_listening_sockets, ngx_pool, 10, sizeof(ngx_listen_t), 1); @@ -86,7 +85,8 @@ int main(int argc, char *const *argv) ngx_create_array(ngx_pool, 10, sizeof(ngx_str_t)), 1); conf.pool = ngx_pool; conf.log = &ngx_log; - conf.type = NGX_CORE_MODULE_TYPE; + conf.module_type = NGX_CORE_MODULE_TYPE; + conf.cmd_type = NGX_MAIN_CONF; conf_file.len = sizeof("nginx.conf") - 1; conf_file.data = "nginx.conf"; 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 @@ -76,11 +76,21 @@ ngx_log_debug(cf->log, "token %d" _ rc); if (cf->handler) { - if ((*cf->handler)(cf) == NGX_CONF_ERROR) { + rv = (*cf->handler)(cf, NULL, cf->handler_conf); + if (rv == NGX_CONF_OK) { + continue; + + } else if (rv == NGX_CONF_ERROR) { + return NGX_CONF_ERROR; + + } else { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "%s %s in %s:%d", + name->data, rv, + cf->conf_file->file.name.data, + cf->conf_file->line); return NGX_CONF_ERROR; } - - continue; } name = (ngx_str_t *) cf->args->elts; @@ -88,7 +98,7 @@ ngx_log_debug(cf->log, "token %d" _ rc); for (i = 0; !found && ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CONF_MODULE_TYPE - && ngx_modules[i]->type != cf->type) + && ngx_modules[i]->type != cf->module_type) { continue; } @@ -107,6 +117,16 @@ ngx_log_debug(cf->log, "token %d" _ rc); ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data); #endif + if ((cmd->type & cf->cmd_type) == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "directive \"%s\" in %s:%d " + "is not allowed here", + name->data, + cf->conf_file->file.name.data, + cf->conf_file->line); + return NGX_CONF_ERROR; + } + if (!(cmd->type & NGX_CONF_ANY) && ((cmd->type & NGX_CONF_FLAG && cf->args->nelts != 2) || (!(cmd->type & NGX_CONF_FLAG) 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 @@ -12,6 +12,12 @@ #include +/* + * AAAA number of agruments + * TT command flags + * LL command location + */ + #define NGX_CONF_NOARGS 1 #define NGX_CONF_TAKE1 2 #define NGX_CONF_TAKE2 4 @@ -20,6 +26,9 @@ #define NGX_CONF_BLOCK 0x020000 #define NGX_CONF_FLAG 0x040000 +#define NGX_MAIN_CONF 0x1000000 + + #define NGX_CONF_UNSET -1 @@ -65,17 +74,24 @@ typedef struct { } ngx_conf_file_t; +typedef char *(*ngx_conf_handler_pt)(ngx_conf_t *cf, + ngx_command_t *dummy, char *conf); + + struct ngx_conf_s { - char *name; - ngx_array_t *args; + char *name; + ngx_array_t *args; - ngx_pool_t *pool; - ngx_conf_file_t *conf_file; - ngx_log_t *log; + ngx_pool_t *pool; + ngx_conf_file_t *conf_file; + ngx_log_t *log; - void *ctx; - int type; - char *(*handler)(ngx_conf_t *cf); + void *ctx; + int module_type; + int cmd_type; + + ngx_conf_handler_pt handler; + char *handler_conf; }; @@ -84,6 +100,10 @@ struct ngx_conf_s { conf = (prev == NGX_CONF_UNSET) ? default : prev; \ } +#define ngx_conf_msec_merge(conf, prev, default) \ + if (conf == NGX_CONF_UNSET) { \ + conf = (prev == NGX_CONF_UNSET) ? default : prev; \ + } #define ngx_conf_size_merge(conf, prev, default) \ if (conf == (size_t) NGX_CONF_UNSET) { \ diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -157,6 +157,8 @@ ngx_log_error(NGX_LOG_DEBUG, r->connecti + index[i].len; } +/* STUB */ r->exten.len = 4; r->exten.data = "html"; + return ngx_http_internal_redirect(r, loc); } diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c --- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -14,16 +15,22 @@ ngx_http_module_t ngx_http_static_modul int ngx_http_static_handler(ngx_http_request_t *r) { - int rc; + int rc, key, i; + ngx_log_e level; ngx_err_t err; ngx_hunk_t *h; + ngx_http_type_t *type; ngx_http_log_ctx_t *ctx; + ngx_http_core_loc_conf_t *core_lcf; + + core_lcf = (ngx_http_core_loc_conf_t *) + ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); #if 0 - ngx_http_event_static_handler_loc_conf_t *cf; + ngx_http_event_static_handler_loc_conf_t *lcf; - cf = (ngx_http_event_static_handler_loc_conf_t *) - ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module); + lcf = (ngx_http_event_static_handler_loc_conf_t *) + ngx_get_module_loc_conf(r, &ngx_http_event_static_handler_module_ctx); #endif @@ -31,32 +38,34 @@ int ngx_http_static_handler(ngx_http_req ctx = r->connection->log->data; ctx->action = "sending response"; - if (r->file.fd == NGX_INVALID_FILE) + if (r->file.fd == NGX_INVALID_FILE) { r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY); - if (r->file.fd == NGX_INVALID_FILE) { - err = ngx_errno; - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "ngx_http_static_handler: " - ngx_open_file_n " %s failed", r->file.name.data); + if (r->file.fd == NGX_INVALID_FILE) { + err = ngx_errno; + + if (err == NGX_ENOENT || err == NGX_ENOTDIR) { + level = NGX_LOG_ERR; + rc = NGX_HTTP_NOT_FOUND; - if (err == NGX_ENOENT || err == NGX_ENOTDIR) { - return NGX_HTTP_NOT_FOUND; + } else { + level = NGX_LOG_CRIT; + rc = NGX_HTTP_INTERNAL_SERVER_ERROR; + } - } else { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + ngx_log_error(level, r->connection->log, ngx_errno, + ngx_open_file_n " %s failed", r->file.name.data); + return rc; } } if (!r->file.info_valid) { if (ngx_stat_fd(r->file.fd, &r->file.info) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "ngx_http_static_handler: " + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_stat_fd_n " %s failed", r->file.name.data); if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "ngx_http_static_handler: " + ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_file_n " %s failed", r->file.name.data); return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -65,16 +74,14 @@ int ngx_http_static_handler(ngx_http_req r->file.info_valid = 1; } -#if !(WIN32) /* it's probably Unix specific */ +#if !(WIN32) /* not regular files is probably Unix specific */ if (!ngx_is_file(r->file.info)) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "ngx_http_static_handler: " + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, "%s is not regular file", r->file.name.data); if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, - "ngx_http_static_handler: " + ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_file_n " %s failed", r->file.name.data); return NGX_HTTP_NOT_FOUND; @@ -93,30 +100,29 @@ int ngx_http_static_handler(ngx_http_req r->headers_out.content_type->key.len = 12; r->headers_out.content_type->key.data = "Content-Type"; - /* STUB */ if (r->exten.len) { - if (ngx_strcasecmp(r->exten.data, "html") == 0) { - r->headers_out.content_type->value.len = 25; - r->headers_out.content_type->value.data = - "text/html; charset=koi8-r"; - } else if (ngx_strcasecmp(r->exten.data, "gif") == 0) { - r->headers_out.content_type->value.len = 9; - r->headers_out.content_type->value.data = "image/gif"; - } else if (ngx_strcasecmp(r->exten.data, "jpg") == 0) { - r->headers_out.content_type->value.len = 10; - r->headers_out.content_type->value.data = "image/jpeg"; - } else if (ngx_strcasecmp(r->exten.data, "pdf") == 0) { - r->headers_out.content_type->value.len = 15; - r->headers_out.content_type->value.data = "application/pdf"; + ngx_http_types_hash_key(key, r->exten); + + type = (ngx_http_type_t *) core_lcf->types[key].elts; + for (i = 0; i < core_lcf->types[key].nelts; i++) { + if (r->exten.len != type[i].exten.len) { + continue; + } + + if (ngx_strcasecmp(r->exten.data, type[i].exten.data) == 0) { + r->headers_out.content_type->value.len = type[i].type.len; + r->headers_out.content_type->value.data = type[i].type.data; + } } + } - } else { + if (r->headers_out.content_type->value.len == 0) { + /* STUB: default type */ r->headers_out.content_type->value.len = 25; r->headers_out.content_type->value.data = "text/html; charset=koi8-r"; } - /**/ - /* we need to allocate them before header would be sent */ + /* we need to allocate all before the header would be sent */ ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), NGX_HTTP_INTERNAL_SERVER_ERROR); diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -42,7 +42,7 @@ static ngx_str_t http_name = ngx_string static ngx_command_t ngx_http_commands[] = { {ngx_string("http"), - NGX_CONF_BLOCK|NGX_CONF_NOARGS, + NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, ngx_http_block, 0, 0}, @@ -69,7 +69,8 @@ static char *ngx_http_block(ngx_conf_t * ngx_array_t in_ports; ngx_listen_t *ls; ngx_http_module_t *module; - ngx_http_conf_ctx_t *ctx, *prev; + ngx_conf_t prev; + ngx_http_conf_ctx_t *ctx; ngx_http_in_port_t *in_port; ngx_http_in_addr_t *in_addr, *inaddr; ngx_http_core_srv_conf_t **cscf; @@ -113,12 +114,12 @@ static char *ngx_http_block(ngx_conf_t * } } - prev = cf->ctx; + prev = *cf; cf->ctx = ctx; - cf->type = NGX_HTTP_MODULE_TYPE; - + cf->module_type = NGX_HTTP_MODULE_TYPE; + cf->cmd_type = NGX_HTTP_MAIN_CONF; rv = ngx_conf_parse(cf, NULL); - cf->ctx = prev; + *cf = prev; if (rv != NGX_CONF_OK) return rv; @@ -147,7 +148,7 @@ static char *ngx_http_block(ngx_conf_t * ngx_init_array(ngx_http_index_handlers, cf->pool, 3, sizeof(ngx_http_handler_pt), NGX_CONF_ERROR); - /* create lists of ports, addresses and server names */ + /* create lists of the ports, the addresses and the server names */ ngx_init_array(in_ports, cf->pool, 10, sizeof(ngx_http_in_port_t), NGX_CONF_ERROR); diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -234,7 +234,7 @@ int ngx_http_init(ngx_pool_t *pool, ngx_ void ngx_http_init_connection(ngx_connection_t *c); int ngx_parse_http_request_line(ngx_http_request_t *r); int ngx_parse_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h); -int ngx_http_handler(ngx_http_request_t *r); +void ngx_http_handler(ngx_http_request_t *r); void ngx_http_finalize_request(ngx_http_request_t *r, int error); void ngx_http_set_write_handler(ngx_http_request_t *r); diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h --- a/src/http/ngx_http_config.h +++ b/src/http/ngx_http_config.h @@ -33,9 +33,9 @@ typedef struct { #define NGX_HTTP_MODULE 0 -#define NGX_HTTP_MAIN_CONF 0x1000000 -#define NGX_HTTP_SRV_CONF 0x2000000 -#define NGX_HTTP_LOC_CONF 0x6000000 +#define NGX_HTTP_MAIN_CONF 0x2000000 +#define NGX_HTTP_SRV_CONF 0x4000000 +#define NGX_HTTP_LOC_CONF 0x8000000 #define NGX_HTTP_SRV_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, srv_conf) diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2,8 +2,8 @@ #include #include - #include +#include #include #include @@ -30,6 +30,7 @@ static char *ngx_http_core_merge_loc_con static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy); static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy); +static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, char *dummy); static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf); @@ -89,6 +90,12 @@ static ngx_command_t ngx_http_core_comm NGX_HTTP_SRV_CONF_OFFSET, 0}, + {ngx_string("types"), + NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, + ngx_types_block, + NGX_HTTP_LOC_CONF_OFFSET, + 0}, + {ngx_string("root"), NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -143,7 +150,7 @@ ngx_module_t ngx_http_core_module = { }; -int ngx_http_handler(ngx_http_request_t *r) +void ngx_http_handler(ngx_http_request_t *r) { int rc, a, n, i; ngx_http_handler_pt *h; @@ -267,16 +274,23 @@ ngx_log_debug(r->connection->log, "trans continue; } - if (rc == NGX_OK) { - break; + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + ngx_http_finalize_request(r, rc); + return; } - if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { - return rc; + if (rc == NGX_OK) { + rc = r->handler(r); + if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { + ngx_http_finalize_request(r, rc); + } + return; } } - return r->handler(r); + /* TODO: no handlers found ? */ + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; } @@ -372,10 +386,7 @@ ngx_log_debug(r->connection->log, "HTTP "ngx_http_core_translate_handler: " ngx_file_type_n " \"%s\" failed", r->file.name.data); - if (err == NGX_ENOENT) { - return NGX_HTTP_NOT_FOUND; - - } else if (err == NGX_ENOTDIR) { + if (err == NGX_ENOENT || err == NGX_ENOTDIR) { return NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { @@ -398,10 +409,7 @@ ngx_log_debug(r->connection->log, "HTTP "ngx_http_core_handler: " ngx_open_file_n " \"%s\" failed", r->file.name.data); - if (err == NGX_ENOENT) { - return NGX_HTTP_NOT_FOUND; - - } else if (err == NGX_ENOTDIR) { + if (err == NGX_ENOENT || err == NGX_ENOTDIR) { return NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { @@ -547,7 +555,8 @@ int ngx_http_internal_redirect(ngx_http_ r->uri_end = uri.data + uri.len; /**/ - return ngx_http_handler(r); + ngx_http_handler(r); + return 0; } @@ -568,7 +577,8 @@ static char *ngx_server_block(ngx_conf_t int i, j; char *rv; ngx_http_module_t *module; - ngx_http_conf_ctx_t *ctx, *prev; + ngx_conf_t pcf; + ngx_http_conf_ctx_t *ctx, *pctx; ngx_http_core_srv_conf_t *scf; ngx_http_core_loc_conf_t **plcf; @@ -606,10 +616,12 @@ static char *ngx_server_block(ngx_conf_t } } - prev = cf->ctx; + pcf = *cf; + pctx = cf->ctx; cf->ctx = ctx; + cf->cmd_type = NGX_HTTP_SRV_CONF; rv = ngx_conf_parse(cf, NULL); - cf->ctx = prev; + *cf = pcf; if (rv != NGX_CONF_OK) return rv; @@ -636,19 +648,19 @@ static char *ngx_server_block(ngx_conf_t } if (module->merge_loc_conf) { - if (module->merge_loc_conf(cf->pool, - prev->loc_conf[module->index], - ctx->loc_conf[module->index]) - == NGX_CONF_ERROR) { - return NGX_CONF_ERROR; + rv = module->merge_loc_conf(cf->pool, + pctx->loc_conf[module->index], + ctx->loc_conf[module->index]); + if (rv != NGX_CONF_OK) { + return rv; } for (j = 0; j < scf->locations.nelts; j++) { - if (module->merge_loc_conf(cf->pool, - ctx->loc_conf[module->index], - plcf[j]->loc_conf[module->index]) - == NGX_CONF_ERROR) { - return NGX_CONF_ERROR; + rv = module->merge_loc_conf(cf->pool, + ctx->loc_conf[module->index], + plcf[j]->loc_conf[module->index]); + if (rv != NGX_CONF_OK) { + return rv; } } } @@ -664,7 +676,8 @@ static char *ngx_location_block(ngx_conf char *rv; ngx_str_t *location; ngx_http_module_t *module; - ngx_http_conf_ctx_t *ctx, *prev; + ngx_conf_t pcf; + ngx_http_conf_ctx_t *ctx, *pctx; ngx_http_core_srv_conf_t *scf; ngx_http_core_loc_conf_t *lcf, **plcf; @@ -672,8 +685,8 @@ static char *ngx_location_block(ngx_conf ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)), NGX_CONF_ERROR); - prev = (ngx_http_conf_ctx_t *) cf->ctx; - ctx->srv_conf = prev->srv_conf; + pctx = (ngx_http_conf_ctx_t *) cf->ctx; + ctx->srv_conf = pctx->srv_conf; ngx_test_null(ctx->loc_conf, ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module), @@ -705,9 +718,62 @@ static char *ngx_location_block(ngx_conf ngx_test_null(plcf, ngx_push_array(&scf->locations), NGX_CONF_ERROR); *plcf = lcf; + pcf = *cf; cf->ctx = ctx; + cf->cmd_type = NGX_HTTP_LOC_CONF; rv = ngx_conf_parse(cf, NULL); - cf->ctx = prev; + *cf = pcf; + + return rv; +} + + +static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, char *conf) +{ + ngx_http_core_loc_conf_t *lcf = (ngx_http_core_loc_conf_t *) conf; + + int i, key; + ngx_str_t *args; + ngx_http_type_t *t; + + if (lcf->types == NULL) { + ngx_test_null(lcf->types, + ngx_palloc(cf->pool, NGX_HTTP_TYPES_HASH_PRIME + * sizeof(ngx_array_t)), + NGX_CONF_ERROR); + + for (i = 0; i < NGX_HTTP_TYPES_HASH_PRIME; i++) { + ngx_init_array(lcf->types[i], cf->pool, 5, sizeof(ngx_http_type_t), + NGX_CONF_ERROR); + } + } + + args = (ngx_str_t *) cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + ngx_http_types_hash_key(key, args[i]); + + ngx_test_null(t, ngx_push_array(&lcf->types[key]), NGX_CONF_ERROR); + t->exten.len = args[i].len; + t->exten.data = args[i].data; + t->type.len = args[0].len; + t->type.data = args[0].data; + } + + return NGX_CONF_OK; +} + + +static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, char *conf) +{ + char *rv; + ngx_conf_t pcf; + + pcf = *cf; + cf->handler = ngx_set_type; + cf->handler_conf = conf; + rv = ngx_conf_parse(cf, NULL); + *cf = pcf; return rv; } @@ -776,29 +842,95 @@ static void *ngx_http_core_create_loc_co ngx_pcalloc(pool, sizeof(ngx_http_core_loc_conf_t)), NGX_CONF_ERROR); - lcf->doc_root.len = 4; - lcf->doc_root.data = "html"; - - lcf->sendfile = 0; +/* + ngx_pcalloc(): - lcf->send_timeout = 10000; - lcf->discarded_buffer_size = 1500; - lcf->lingering_time = 30000; - lcf->lingering_timeout = 5000; + lcf->doc_root.len = 0; + lcf->doc_root.data = NULL; + lcf->types = NULL; +*/ -/* + lcf->sendfile = NGX_CONF_UNSET; + lcf->send_timeout = NGX_CONF_UNSET; -*/ + lcf->discarded_buffer_size = NGX_CONF_UNSET; + lcf->lingering_time = NGX_CONF_UNSET; + lcf->lingering_timeout = NGX_CONF_UNSET; return lcf; } + +static ngx_http_type_t default_types[] = { + { ngx_string("html"), ngx_string("text/html") }, + { ngx_string("gif"), ngx_string("image/gif") }, + { ngx_string("jpg"), ngx_string("image/jpeg") }, + { ngx_null_string, ngx_null_string } +}; + + static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool, void *parent, void *child) { + ngx_http_core_loc_conf_t *prev = (ngx_http_core_loc_conf_t *) parent; + ngx_http_core_loc_conf_t *conf = (ngx_http_core_loc_conf_t *) child; + + int i, key; + ngx_http_type_t *t; + + if (conf->doc_root.len == 0) { + if (prev->doc_root.len) { + conf->doc_root.len = prev->doc_root.len; + conf->doc_root.data = prev->doc_root.data; + + } else { + conf->doc_root.len = 4; + conf->doc_root.data = "html"; + } + } + + if (conf->types == NULL) { + if (prev->types) { + conf->types = prev->types; + + } else { + ngx_test_null(conf->types, + ngx_palloc(pool, NGX_HTTP_TYPES_HASH_PRIME + * sizeof(ngx_array_t)), + NGX_CONF_ERROR); + + for (i = 0; i < NGX_HTTP_TYPES_HASH_PRIME; i++) { + ngx_init_array(conf->types[i], pool, 5, sizeof(ngx_http_type_t), + NGX_CONF_ERROR); + } + + for (i = 0; default_types[i].exten.len; i++) { + ngx_http_types_hash_key(key, default_types[i].exten); + + ngx_test_null(t, ngx_push_array(&conf->types[key]), + NGX_CONF_ERROR); + t->exten.len = default_types[i].exten.len; + t->exten.data = default_types[i].exten.data; + t->type.len = default_types[i].type.len; + t->type.data = default_types[i].type.data; + } + } + } + + ngx_conf_merge(conf->sendfile, prev->sendfile, 0); + + ngx_conf_msec_merge(conf->send_timeout, prev->send_timeout, 10000); + + ngx_conf_size_merge(conf->discarded_buffer_size, + prev->discarded_buffer_size, 1500); + + ngx_conf_msec_merge(conf->lingering_time, prev->lingering_time, 30000); + ngx_conf_msec_merge(conf->lingering_timeout, prev->lingering_timeout, 5000); + return NGX_CONF_OK; } + static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, char *conf) { ngx_str_t *args; @@ -817,7 +949,7 @@ static char *ngx_set_listen(ngx_conf_t * args = (ngx_str_t *) cf->args->elts; - ls->port = atoi(args[1].data); + ls->port = ngx_atoi(args[1].data, args[1].len); if (ls->port < 1 || ls->port > 65536) { return "port must be between 1 and 65535"; } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -50,6 +50,21 @@ typedef struct { } ngx_http_server_name_t; +#define NGX_HTTP_TYPES_HASH_PRIME 13 + +#define ngx_http_types_hash_key(key, ext) \ + { \ + int n; \ + for (key = 0, n = 0; n < ext.len; n++) { \ + key += ext.data[n]; \ + } \ + key %= NGX_HTTP_TYPES_HASH_PRIME; \ + } + +typedef struct { + ngx_str_t exten; + ngx_str_t type; +} ngx_http_type_t; typedef struct { @@ -61,6 +76,8 @@ typedef struct { ngx_str_t doc_root; /* root */ + ngx_array_t *types; + int sendfile; /* sendfile */ time_t send_timeout; /* send_timeout */ size_t send_lowat; /* send_lowa */ diff --git a/src/http/ngx_http_header_filter.c b/src/http/ngx_http_header_filter.c --- a/src/http/ngx_http_header_filter.c +++ b/src/http/ngx_http_header_filter.c @@ -65,7 +65,7 @@ static ngx_str_t http_codes[] = { ngx_null_string, /* 412 */ ngx_string("413 Request Entity Too Large"), ngx_null_string, /* "414 Request-URI Too Large" but we never send it - because we treat such requests as HTTP/0.9 requests + because we treat such requests as the HTTP/0.9 requests and send only the body without the header */ ngx_null_string, /* 415 */ ngx_string("416 Requested Range Not Satisfiable"), @@ -124,16 +124,20 @@ static int ngx_http_header_filter(ngx_ht } else { if (r->headers_out.status < NGX_HTTP_MOVED_PERMANENTLY) { + /* 2XX */ status = r->headers_out.status - NGX_HTTP_OK; } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) { + /* 3XX */ status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + 1; r->header_only = 1; } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) { + /* 4XX */ status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + 1 + 4; } else { + /* 5XX */ status = r->headers_out.status - NGX_HTTP_INTERNAL_SERVER_ERROR + 1 + 4 + 17; } diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -120,6 +120,7 @@ int ngx_http_special_response_handler(ng r->headers_out.status = error; if (error < NGX_HTTP_BAD_REQUEST) { + /* 3XX */ err = error - NGX_HTTP_MOVED_PERMANENTLY; } else { @@ -133,9 +134,11 @@ int ngx_http_special_response_handler(ng r->headers_out.content_type->value.data = "text/html"; if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) { + /* 4XX */ err = error - NGX_HTTP_BAD_REQUEST + 3; } else { + /* 5XX */ err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17; } } @@ -149,6 +152,15 @@ int ngx_http_special_response_handler(ng } } + if (r->lingering_close == 1) { + switch (error) { + case NGX_HTTP_BAD_REQUEST: + case NGX_HTTP_REQUEST_URI_TOO_LARGE: + case NGX_HTTP_INTERNAL_SERVER_ERROR: + r->lingering_close = 0; + } + } + if (error_pages[err].len == 0) { r->headers_out.content_length = -1; } else { diff --git a/src/os/unix/ngx_freebsd_init.c b/src/os/unix/ngx_freebsd_init.c --- a/src/os/unix/ngx_freebsd_init.c +++ b/src/os/unix/ngx_freebsd_init.c @@ -2,19 +2,41 @@ #include -int freebsd_kern_osreldate; -int freebsd_hw_ncpu; - -int freebsd_sendfile_nbytes_bug; +char ngx_freebsd_kern_ostype[20]; +char ngx_freebsd_kern_osrelease[20]; +int ngx_freebsd_kern_osreldate; +int ngx_freebsd_hw_ncpu; +int ngx_freebsd_net_inet_tcp_sendspace; +int ngx_freebsd_sendfile_nbytes_bug; int ngx_os_init(ngx_log_t *log) { size_t size; + size = 20; + if (sysctlbyname("kern.ostype", + ngx_freebsd_kern_ostype, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, errno, + "sysctlbyname(kern.ostype) failed"); + return NGX_ERROR; + } + + size = 20; + if (sysctlbyname("kern.osrelease", + ngx_freebsd_kern_osrelease, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, errno, + "sysctlbyname(kern.osrelease) failed"); + return NGX_ERROR; + } + + ngx_log_error(NGX_LOG_INFO, log, 0, "OS: %s %s", + ngx_freebsd_kern_ostype, ngx_freebsd_kern_osrelease); + + size = 4; if (sysctlbyname("kern.osreldate", - &freebsd_kern_osreldate, &size, NULL, 0) == -1) { + &ngx_freebsd_kern_osreldate, &size, NULL, 0) == -1) { ngx_log_error(NGX_LOG_ALERT, log, errno, "sysctlbyname(kern.osreldate) failed"); return NGX_ERROR; @@ -22,7 +44,7 @@ int ngx_os_init(ngx_log_t *log) ngx_log_error(NGX_LOG_INFO, log, 0, "kern.osreldate: %d, built on %d", - freebsd_kern_osreldate, __FreeBSD_version); + ngx_freebsd_kern_osreldate, __FreeBSD_version); #if HAVE_FREEBSD_SENDFILE @@ -42,12 +64,12 @@ int ngx_os_init(ngx_log_t *log) || __FreeBSD_version == 460002 || __FreeBSD_version >= 500039 /* a new syscall without the bug */ - freebsd_sendfile_nbytes_bug = 0; + ngx_freebsd_sendfile_nbytes_bug = 0; #else /* an old syscall that can have the bug */ - freebsd_sendfile_nbytes_bug = 1; + ngx_freebsd_sendfile_nbytes_bug = 1; #endif @@ -55,13 +77,27 @@ int ngx_os_init(ngx_log_t *log) size = 4; - if (sysctlbyname("hw.ncpu", &freebsd_hw_ncpu, &size, NULL, 0) == -1) { + if (sysctlbyname("hw.ncpu", &ngx_freebsd_hw_ncpu, &size, NULL, 0) == -1) { ngx_log_error(NGX_LOG_ALERT, log, errno, "sysctlbyname(hw.ncpu) failed"); return NGX_ERROR; } - ngx_log_error(NGX_LOG_INFO, log, 0, "hw.ncpu: %d", freebsd_hw_ncpu); + ngx_log_error(NGX_LOG_INFO, log, 0, "hw.ncpu: %d", ngx_freebsd_hw_ncpu); + + + size = 4; + if (sysctlbyname("net.inet.tcp.sendspace", + &ngx_freebsd_net_inet_tcp_sendspace, + &size, NULL, 0) == -1) + { + ngx_log_error(NGX_LOG_ALERT, log, errno, + "sysctlbyname(net.inet.tcp.sendspace) failed"); + return NGX_ERROR; + } + + ngx_log_error(NGX_LOG_INFO, log, 0, "net.inet.tcp.sendspace: %d", + ngx_freebsd_net_inet_tcp_sendspace); return NGX_OK; } diff --git a/src/os/unix/ngx_freebsd_init.h b/src/os/unix/ngx_freebsd_init.h --- a/src/os/unix/ngx_freebsd_init.h +++ b/src/os/unix/ngx_freebsd_init.h @@ -1,5 +1,5 @@ -#ifndef _NGX_OS_INIT_H_INCLUDED_ -#define _NGX_OS_INIT_H_INCLUDED_ +#ifndef _NGX_FREEBSD_INIT_H_INCLUDED_ +#define _NGX_FREEBSD_INIT_H_INCLUDED_ #include @@ -11,8 +11,10 @@ int ngx_os_init(ngx_log_t *log); -extern int freebsd_kern_osreldate; -extern int freebsd_hw_ncpu; +extern int ngx_freebsd_kern_osreldate; +extern int ngx_freebsd_hw_ncpu; +extern int ngx_freebsd_net_inet_tcp_sendspace; +extern int ngx_freebsd_sendfile_nbytes_bug; -#endif /* _NGX_OS_INIT_H_INCLUDED_ */ +#endif /* _NGX_FREEBSD_INIT_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_freebsd_write_chain.c b/src/os/unix/ngx_freebsd_write_chain.c --- a/src/os/unix/ngx_freebsd_write_chain.c +++ b/src/os/unix/ngx_freebsd_write_chain.c @@ -9,6 +9,7 @@ #include #include #include +#include ngx_chain_t *ngx_freebsd_write_chain(ngx_connection_t *c, ngx_chain_t *in) @@ -50,9 +51,9 @@ ngx_chain_t *ngx_freebsd_write_chain(ngx prev = ce->hunk->last; } -#if (HAVE_FREEBSD_SENDFILE_NBYTES_BUG) - hsize += ce->hunk->last - ce->hunk->pos; -#endif + if (ngx_freebsd_sendfile_nbytes_bug) { + hsize += ce->hunk->last - ce->hunk->pos; + } ce = ce->next; } } diff --git a/src/os/unix/ngx_os_init.h b/src/os/unix/ngx_os_init.h new file mode 100644 --- /dev/null +++ b/src/os/unix/ngx_os_init.h @@ -0,0 +1,12 @@ +#ifndef _NGX_OS_INIT_H_INCLUDED_ +#define _NGX_OS_INIT_H_INCLUDED_ + + +#include +#include + + +int ngx_os_init(ngx_log_t *log); + + +#endif /* _NGX_OS_INIT_H_INCLUDED_ */