mirror of
https://github.com/nginx/nginx.git
synced 2024-11-24 04:49:01 +08:00
nginx-0.0.1-2003-06-02-19:24:30 import
This commit is contained in:
parent
aa3436c04c
commit
7578ec9df4
@ -32,7 +32,7 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
|
||||
|
||||
/* open configuration file */
|
||||
|
||||
fd = ngx_open_file(filename->data, NGX_FILE_RDONLY);
|
||||
fd = ngx_open_file(filename->data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
|
||||
if (fd == NGX_INVALID_FILE) {
|
||||
ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno,
|
||||
ngx_open_file_n " %s failed", filename->data);
|
||||
@ -142,7 +142,7 @@ ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data);
|
||||
if (cmd->type & argument_number[cf->args->nelts - 1]) {
|
||||
valid = 1;
|
||||
|
||||
} else if (cmd->type & NGX_CONF_ANY1) {
|
||||
} else if (cmd->type & NGX_CONF_1MORE) {
|
||||
|
||||
if (cf->args->nelts != 1) {
|
||||
valid = 1;
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define NGX_CONF_TAKE2 0x00000004
|
||||
#define NGX_CONF_ARGS_NUMBER 0x0000ffff
|
||||
#define NGX_CONF_ANY 0x00010000
|
||||
#define NGX_CONF_ANY1 0x00020000
|
||||
#define NGX_CONF_1MORE 0x00020000
|
||||
#define NGX_CONF_BLOCK 0x00040000
|
||||
#define NGX_CONF_FLAG 0x00080000
|
||||
|
||||
|
@ -61,6 +61,7 @@ struct ngx_connection_s {
|
||||
|
||||
unsigned pipeline:1;
|
||||
unsigned unexpected_eof:1;
|
||||
unsigned tcp_nopush:1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@ typedef struct ngx_event_s ngx_event_t;
|
||||
#include <ngx_array.h>
|
||||
#include <ngx_string.h>
|
||||
#include <ngx_file.h>
|
||||
#include <ngx_inet.h>
|
||||
#include <ngx_conf_file.h>
|
||||
#include <ngx_os_init.h>
|
||||
#include <ngx_connection.h>
|
||||
|
@ -71,11 +71,9 @@ ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size,
|
||||
int before, int after);
|
||||
|
||||
#define ngx_alloc_hunk(pool) ngx_palloc(pool, sizeof(ngx_hunk_t))
|
||||
#define ngx_alloc_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
|
||||
#define ngx_calloc_hunk(pool) ngx_pcalloc(pool, sizeof(ngx_hunk_t))
|
||||
|
||||
/* STUB */
|
||||
#define ngx_create_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
|
||||
/**/
|
||||
#define ngx_alloc_chain_entry(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
|
||||
|
||||
#define ngx_add_hunk_to_chain(chain, h, pool, error) \
|
||||
do { \
|
||||
|
@ -29,10 +29,16 @@ extern ngx_module_t ngx_http_write_filter_module;
|
||||
extern ngx_module_t ngx_http_output_filter_module;
|
||||
extern ngx_module_t ngx_http_header_filter_module;
|
||||
|
||||
extern ngx_module_t ngx_http_chunked_filter_module;
|
||||
extern ngx_module_t ngx_http_range_filter_module;
|
||||
extern ngx_module_t ngx_http_charset_filter_module;
|
||||
|
||||
extern ngx_module_t ngx_http_index_module;
|
||||
extern ngx_module_t ngx_http_static_module;
|
||||
extern ngx_module_t ngx_http_proxy_module;
|
||||
|
||||
extern ngx_module_t ngx_http_log_module;
|
||||
|
||||
|
||||
ngx_module_t *ngx_modules[] = {
|
||||
|
||||
@ -64,13 +70,17 @@ ngx_module_t *ngx_modules[] = {
|
||||
&ngx_http_output_filter_module,
|
||||
&ngx_http_header_filter_module,
|
||||
|
||||
&ngx_http_chunked_filter_module,
|
||||
/* &ngx_http_gzip_filter_module, */
|
||||
/* &ngx_http_range_filter_module, */
|
||||
&ngx_http_range_filter_module,
|
||||
/* &ngx_http_ssi_filter_module, */
|
||||
&ngx_http_charset_filter_module,
|
||||
|
||||
&ngx_http_index_module,
|
||||
/* &ngx_http_static_module, */
|
||||
/* &ngx_http_proxy_module, */
|
||||
|
||||
&ngx_http_log_module,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
@ -5,17 +5,6 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
#if 0
|
||||
#include <ngx_types.h>
|
||||
#include <ngx_time.h>
|
||||
#include <ngx_socket.h>
|
||||
#include <ngx_log.h>
|
||||
#include <ngx_alloc.h>
|
||||
#include <ngx_array.h>
|
||||
#include <ngx_conf_file.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define NGX_INVALID_INDEX 0x80000000
|
||||
|
||||
@ -310,10 +299,6 @@ extern int ngx_event_flags;
|
||||
#endif
|
||||
|
||||
|
||||
#if !(HAVE_EPOLL)
|
||||
#define ngx_edge_add_event(ev) NGX_ERROR
|
||||
#endif
|
||||
|
||||
|
||||
#define NGX_EVENT_MODULE 0x544E5645 /* "EVNT" */
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
#include <ngx_event.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
void ngx_event_accept(ngx_event_t *ev)
|
||||
@ -30,9 +28,11 @@ void ngx_event_accept(ngx_event_t *ev)
|
||||
|
||||
do {
|
||||
|
||||
/* Create the pool before accept() to avoid copy the sockaddr.
|
||||
Although accept() can fail it's uncommon case
|
||||
and the pool can be got from the free pool list */
|
||||
/*
|
||||
* Create the pool before accept() to avoid copy the sockaddr.
|
||||
* Although accept() can fail it's uncommon case
|
||||
* and the pool can be got from the free pool list
|
||||
*/
|
||||
|
||||
pool = ngx_create_pool(ls->pool_size, ev->log);
|
||||
if (pool == NULL) {
|
||||
@ -168,7 +168,7 @@ void ngx_event_accept(ngx_event_t *ev)
|
||||
ngx_memcpy(c->log, ev->log, sizeof(ngx_log_t));
|
||||
rev->log = wev->log = c->log;
|
||||
|
||||
/* STUB: x86: MT: lock xadd, MP: lock xadd, shared */
|
||||
/* TODO: x86: MT: lock xadd, MP: lock xadd, shared */
|
||||
c->number = ngx_connection_counter++;
|
||||
|
||||
ngx_log_debug(ev->log, "accept: %d, %d" _ s _ c->number);
|
||||
|
124
src/http/modules/ngx_http_charset_filter.c
Normal file
124
src/http/modules/ngx_http_charset_filter.c
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t default_charset;
|
||||
} ngx_http_charset_loc_conf_t;
|
||||
|
||||
|
||||
static void *ngx_http_charset_create_loc_conf(ngx_pool_t *pool);
|
||||
static char *ngx_http_charset_merge_loc_conf(ngx_pool_t *pool,
|
||||
void *parent, void *child);
|
||||
static int ngx_http_charset_filter_init(ngx_pool_t *pool);
|
||||
|
||||
|
||||
static ngx_command_t ngx_http_charset_filter_commands[] = {
|
||||
|
||||
{ngx_string("default_charset"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_str_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_charset_loc_conf_t, default_charset),
|
||||
NULL},
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
static ngx_http_module_t ngx_http_charset_filter_module_ctx = {
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
ngx_http_charset_create_loc_conf, /* create location configuration */
|
||||
ngx_http_charset_merge_loc_conf /* merge location configuration */
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_http_charset_filter_module = {
|
||||
NGX_MODULE,
|
||||
&ngx_http_charset_filter_module_ctx, /* module context */
|
||||
ngx_http_charset_filter_commands, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
ngx_http_charset_filter_init /* init module */
|
||||
};
|
||||
|
||||
|
||||
static int (*next_header_filter) (ngx_http_request_t *r);
|
||||
#if 0
|
||||
static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
|
||||
#endif
|
||||
|
||||
|
||||
static int ngx_http_charset_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_http_charset_loc_conf_t *lcf;
|
||||
|
||||
lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
|
||||
|
||||
if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
|
||||
&& r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
|
||||
{
|
||||
/* do not set charset for the redirect because NN 4.x uses this
|
||||
charset instead of the next page charset */
|
||||
r->headers_out.charset.len = 0;
|
||||
|
||||
} else if (r->headers_out.charset.len == 0) {
|
||||
r->headers_out.charset = lcf->default_charset;
|
||||
}
|
||||
|
||||
return next_header_filter(r);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static int ngx_http_charset_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
{
|
||||
ngx_log_debug(r->connection->log, "CHARSET BODY");
|
||||
return next_body_filter(r, in);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int ngx_http_charset_filter_init(ngx_pool_t *pool)
|
||||
{
|
||||
next_header_filter = ngx_http_top_header_filter;
|
||||
ngx_http_top_header_filter = ngx_http_charset_header_filter;
|
||||
|
||||
#if 0
|
||||
next_body_filter = ngx_http_top_body_filter;
|
||||
ngx_http_top_body_filter = ngx_http_charset_body_filter;
|
||||
#endif
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void *ngx_http_charset_create_loc_conf(ngx_pool_t *pool)
|
||||
{
|
||||
ngx_http_charset_loc_conf_t *lcf;
|
||||
|
||||
ngx_test_null(lcf,
|
||||
ngx_pcalloc(pool, sizeof(ngx_http_charset_loc_conf_t)),
|
||||
NGX_CONF_ERROR);
|
||||
|
||||
return lcf;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_charset_merge_loc_conf(ngx_pool_t *pool,
|
||||
void *parent, void *child)
|
||||
{
|
||||
ngx_http_charset_loc_conf_t *prev = parent;
|
||||
ngx_http_charset_loc_conf_t *conf = child;
|
||||
|
||||
ngx_conf_merge_str_value(conf->default_charset,
|
||||
prev->default_charset, "koi8-r");
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
129
src/http/modules/ngx_http_chunked_filter.c
Normal file
129
src/http/modules/ngx_http_chunked_filter.c
Normal file
@ -0,0 +1,129 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
static int ngx_http_chunked_filter_init(ngx_pool_t *pool);
|
||||
|
||||
|
||||
static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
NULL, /* create location configuration */
|
||||
NULL, /* merge location configuration */
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_http_chunked_filter_module = {
|
||||
NGX_MODULE,
|
||||
&ngx_http_chunked_filter_module_ctx, /* module context */
|
||||
NULL, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
ngx_http_chunked_filter_init /* init module */
|
||||
};
|
||||
|
||||
|
||||
static int (*next_header_filter) (ngx_http_request_t *r);
|
||||
static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
|
||||
|
||||
|
||||
static int ngx_http_chunked_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
if (r->headers_out.content_length == -1) {
|
||||
if (r->http_version < NGX_HTTP_VERSION_11) {
|
||||
r->keepalive = 0;
|
||||
|
||||
} else {
|
||||
r->chunked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return next_header_filter(r);
|
||||
}
|
||||
|
||||
|
||||
static int ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
{
|
||||
char *chunk;
|
||||
size_t size, len;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t *out, *ce, *te, **le;
|
||||
|
||||
if (in == NULL || !r->chunked) {
|
||||
return next_body_filter(r, in);
|
||||
}
|
||||
|
||||
ngx_test_null(out, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
le = &out->next;
|
||||
|
||||
size = 0;
|
||||
ce = in;
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
if (ce->hunk->type & NGX_HUNK_IN_MEMORY) {
|
||||
size += ce->hunk->last - ce->hunk->pos;
|
||||
} else {
|
||||
size += (size_t) (ce->hunk->file_last - ce->hunk->file_pos);
|
||||
}
|
||||
|
||||
ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
te->hunk = ce->hunk;
|
||||
*le = te;
|
||||
le = &te->next;
|
||||
|
||||
if (ce->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
ce = ce->next;
|
||||
}
|
||||
|
||||
ngx_test_null(chunk, ngx_palloc(r->pool, 11), NGX_ERROR);
|
||||
len = ngx_snprintf(chunk, 11, "%x" CRLF, size);
|
||||
|
||||
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
|
||||
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
|
||||
h->pos = chunk;
|
||||
h->last = chunk + len;
|
||||
|
||||
out->hunk = h;
|
||||
|
||||
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
|
||||
|
||||
if (ce->hunk->type & NGX_HUNK_LAST) {
|
||||
ce->hunk->type &= ~NGX_HUNK_LAST;
|
||||
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY|NGX_HUNK_LAST;
|
||||
h->pos = CRLF "0" CRLF CRLF;
|
||||
h->last = h->pos + 7;
|
||||
|
||||
} else {
|
||||
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY;
|
||||
h->pos = CRLF;
|
||||
h->last = h->pos + 2;
|
||||
}
|
||||
|
||||
ngx_test_null(te, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
te->hunk = h;
|
||||
te->next = NULL;
|
||||
*le = te;
|
||||
|
||||
return next_body_filter(r, out);
|
||||
}
|
||||
|
||||
|
||||
static int ngx_http_chunked_filter_init(ngx_pool_t *pool)
|
||||
{
|
||||
next_header_filter = ngx_http_top_header_filter;
|
||||
ngx_http_top_header_filter = ngx_http_chunked_header_filter;
|
||||
|
||||
next_body_filter = ngx_http_top_body_filter;
|
||||
ngx_http_top_body_filter = ngx_http_chunked_body_filter;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
@ -1,5 +1,16 @@
|
||||
|
||||
#include <ngx_http_index_handler.h>
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_array_t indices;
|
||||
size_t max_index_len;
|
||||
} ngx_http_index_conf_t;
|
||||
|
||||
|
||||
#define NGX_HTTP_DEFAULT_INDEX "index.html"
|
||||
|
||||
|
||||
static int ngx_http_index_test_dir(ngx_http_request_t *r);
|
||||
@ -14,7 +25,7 @@ static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
static ngx_command_t ngx_http_index_commands[] = {
|
||||
|
||||
{ngx_string("index"),
|
||||
NGX_HTTP_LOC_CONF|NGX_CONF_ANY1,
|
||||
NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
|
||||
ngx_http_index_set_index,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
0,
|
||||
@ -46,8 +57,8 @@ ngx_module_t ngx_http_index_module = {
|
||||
|
||||
|
||||
/*
|
||||
Try to open first index file before the test of the directory existence
|
||||
because the valid requests should be many more then invalid ones.
|
||||
Try to open the first index file before the directory existence test
|
||||
because the valid requests should be many more than invalid ones.
|
||||
If open() failed then stat() should be more quickly because some data
|
||||
is already cached in the kernel.
|
||||
Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
|
||||
@ -57,7 +68,7 @@ ngx_module_t ngx_http_index_module = {
|
||||
|
||||
int ngx_http_index_handler(ngx_http_request_t *r)
|
||||
{
|
||||
int i, rc, test_dir;
|
||||
int i, rc, test_dir, path_not_found;
|
||||
char *name, *file;
|
||||
ngx_str_t redirect, *index;
|
||||
ngx_err_t err;
|
||||
@ -80,6 +91,7 @@ int ngx_http_index_handler(ngx_http_request_t *r)
|
||||
r->path.len = file - r->path.data;
|
||||
|
||||
test_dir = 1;
|
||||
path_not_found = 1;
|
||||
|
||||
index = icf->indices.elts;
|
||||
for (i = 0; i < icf->indices.nelts; i++) {
|
||||
@ -92,7 +104,7 @@ int ngx_http_index_handler(ngx_http_request_t *r)
|
||||
name = index[i].data;
|
||||
}
|
||||
|
||||
fd = ngx_open_file(name, NGX_FILE_RDONLY);
|
||||
fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
|
||||
if (fd == NGX_INVALID_FILE) {
|
||||
err = ngx_errno;
|
||||
|
||||
@ -100,7 +112,7 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
|
||||
"DEBUG: " ngx_open_file_n " %s failed", name);
|
||||
|
||||
if (err == NGX_ENOTDIR) {
|
||||
r->path_not_found = 1;
|
||||
path_not_found = 1;
|
||||
|
||||
} else if (err == NGX_EACCES) {
|
||||
r->path_err = err;
|
||||
@ -108,7 +120,7 @@ ngx_log_error(NGX_LOG_DEBUG, r->connection->log, err,
|
||||
}
|
||||
|
||||
if (test_dir) {
|
||||
if (r->path_not_found) {
|
||||
if (path_not_found) {
|
||||
r->path_err = err;
|
||||
return NGX_HTTP_NOT_FOUND;
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
#ifndef _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_
|
||||
#define _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#define NGX_HTTP_DEFAULT_INDEX "index.html"
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_array_t indices;
|
||||
size_t max_index_len;
|
||||
} ngx_http_index_conf_t;
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_index_module;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_INDEX_HANDLER_H_INCLUDED_ */
|
@ -1,38 +1,82 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_string.h>
|
||||
#include <ngx_alloc.h>
|
||||
#include <ngx_time.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_config.h>
|
||||
|
||||
|
||||
ngx_http_module_t ngx_http_log_module;
|
||||
typedef struct {
|
||||
ngx_file_t file;
|
||||
} ngx_http_log_conf_t;
|
||||
|
||||
|
||||
static void *ngx_http_log_create_conf(ngx_pool_t *pool);
|
||||
static char *ngx_http_log_merge_conf(ngx_pool_t *p, void *parent, void *child);
|
||||
static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
static ngx_command_t ngx_http_log_commands[] = {
|
||||
|
||||
{ngx_string("access_log"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_http_log_set_log,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
0,
|
||||
NULL},
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
ngx_http_module_t ngx_http_log_module_ctx = {
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
ngx_http_log_create_conf, /* create location configration */
|
||||
ngx_http_log_merge_conf /* merge location configration */
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_http_log_module = {
|
||||
NGX_MODULE,
|
||||
&ngx_http_log_module_ctx, /* module context */
|
||||
ngx_http_log_commands, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
NULL, /* init module */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
|
||||
int ngx_http_log_handler(ngx_http_request_t *r)
|
||||
{
|
||||
size_t len;
|
||||
char *line, *p;
|
||||
ngx_tm_t tm;
|
||||
char *line, *p;
|
||||
size_t len;
|
||||
ngx_tm_t tm;
|
||||
ngx_http_log_conf_t *lcf;
|
||||
|
||||
ngx_log_debug(r->connection->log, "log handler");
|
||||
|
||||
/* 10:%con, 1:%pipe, 22:%date, 2:"%r", 3:%status, 20:%bytes,
|
||||
6*" ", 2/1: "\r\n" */
|
||||
lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
|
||||
|
||||
/* 10:%con, 1:%pipe, 22:%date, 2:"%r", 3:%status, 20:%bytes, 2:%user-agent,
|
||||
7*" ", 2/1: "\r\n" */
|
||||
#if (WIN32)
|
||||
len = 10 + 1 + 22 + 2 + 3 + 20 + 6 + 2;
|
||||
len = 10 + 1 + 22 + 2 + 3 + 20 + 2 + 7 + 2;
|
||||
#else
|
||||
len = 10 + 1 + 22 + 2 + 3 + 20 + 6 + 1;
|
||||
len = 10 + 1 + 22 + 2 + 3 + 20 + 2 + 7 + 1;
|
||||
#endif
|
||||
|
||||
len += r->connection->addr_text.len;
|
||||
len += r->request_line.len;
|
||||
if (r->headers_in.user_agent) {
|
||||
len += r->headers_in.user_agent->value.len;
|
||||
}
|
||||
|
||||
ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR);
|
||||
p = line;
|
||||
@ -79,13 +123,80 @@ int ngx_http_log_handler(ngx_http_request_t *r)
|
||||
|
||||
p += ngx_snprintf(p, 21, OFF_FMT, r->connection->sent);
|
||||
|
||||
*p++ = ' ';
|
||||
|
||||
*p++ = '"';
|
||||
if (r->headers_in.user_agent) {
|
||||
ngx_memcpy(p, r->headers_in.user_agent->value.data,
|
||||
r->headers_in.user_agent->value.len);
|
||||
p += r->headers_in.user_agent->value.len;
|
||||
}
|
||||
*p++ = '"';
|
||||
|
||||
#if (WIN32)
|
||||
*p++ = CR; *p++ = LF;
|
||||
#else
|
||||
*p++ = LF;
|
||||
#endif
|
||||
|
||||
write(1, line, p - line);
|
||||
write(lcf->file.fd, line, p - line);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void *ngx_http_log_create_conf(ngx_pool_t *pool)
|
||||
{
|
||||
ngx_http_log_conf_t *conf;
|
||||
|
||||
ngx_test_null(conf, ngx_pcalloc(pool, sizeof(ngx_http_log_conf_t)),
|
||||
NGX_CONF_ERROR);
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_merge_conf(ngx_pool_t *p, void *parent, void *child)
|
||||
{
|
||||
ngx_http_log_conf_t *prev = parent;
|
||||
ngx_http_log_conf_t *conf = child;
|
||||
|
||||
/* STUB */
|
||||
*conf = *prev;
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
ngx_http_log_conf_t *lcf = conf;
|
||||
|
||||
int len;
|
||||
ngx_err_t err;
|
||||
ngx_str_t *value;
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
lcf->file.name.len = value[1].len;
|
||||
lcf->file.name.data = value[1].data;
|
||||
|
||||
lcf->file.fd = ngx_open_file(lcf->file.name.data,
|
||||
NGX_FILE_RDWR,
|
||||
NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
|
||||
|
||||
if (lcf->file.fd == NGX_INVALID_FILE) {
|
||||
err = ngx_errno;
|
||||
len = ngx_snprintf(ngx_conf_errstr, sizeof(ngx_conf_errstr) - 1,
|
||||
ngx_open_file_n " \"%s\" failed (%d: ",
|
||||
lcf->file.name.data, err);
|
||||
len += ngx_strerror_r(err, ngx_conf_errstr + len,
|
||||
sizeof(ngx_conf_errstr) - len - 1);
|
||||
ngx_conf_errstr[len++] = ')';
|
||||
ngx_conf_errstr[len++] = '\0';
|
||||
return ngx_conf_errstr;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
41
src/http/modules/ngx_http_log_handler.h
Normal file
41
src/http/modules/ngx_http_log_handler.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
|
||||
#define _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
int dummy;
|
||||
} ngx_http_log_conf_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
|
||||
NGX_HTTP_LOG_HANDLER = 0,
|
||||
|
||||
#if 0
|
||||
/* the ngx_str_t field of the request */
|
||||
NGX_HTTP_LOG_REQUEST_STR_FIELD,
|
||||
|
||||
/* the ngx_str_t field of the r->headers_in */
|
||||
NGX_HTTP_LOG_REQUEST_HEADER_IN_FIELD,
|
||||
|
||||
/* the ngx_str_t field of the r->headers_out */
|
||||
NGX_HTTP_LOG_REQUEST_HEADER_OUT_FIELD,
|
||||
#endif
|
||||
|
||||
} ngx_http_log_code_e;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
int size;
|
||||
char *(*handler) (ngx_http_request_t *r, char *p);
|
||||
int offset;
|
||||
} ngx_http_log_code_t;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_LOG_HANDLER_H_INCLUDED_ */
|
362
src/http/modules/ngx_http_range_filter.c
Normal file
362
src/http/modules/ngx_http_range_filter.c
Normal file
@ -0,0 +1,362 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t boundary_header;
|
||||
} ngx_http_range_filter_ctx_t;
|
||||
|
||||
|
||||
static int ngx_http_range_filter_init(ngx_pool_t *pool);
|
||||
|
||||
|
||||
static ngx_http_module_t ngx_http_range_filter_module_ctx = {
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
NULL, /* create location configuration */
|
||||
NULL, /* merge location configuration */
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_http_range_filter_module = {
|
||||
NGX_MODULE,
|
||||
&ngx_http_range_filter_module_ctx, /* module context */
|
||||
NULL, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
ngx_http_range_filter_init /* init module */
|
||||
};
|
||||
|
||||
|
||||
static int (*next_header_filter) (ngx_http_request_t *r);
|
||||
static int (*next_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
|
||||
|
||||
|
||||
static int ngx_http_range_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
int rc, boundary, len, i;
|
||||
char *p;
|
||||
off_t start, end;
|
||||
ngx_http_range_t *range;
|
||||
ngx_http_range_filter_ctx_t *ctx;
|
||||
|
||||
if (r->main
|
||||
|| r->http_version < NGX_HTTP_VERSION_10
|
||||
|| r->headers_out.status != NGX_HTTP_OK
|
||||
|| r->headers_out.content_length == -1
|
||||
/* STUB: we currently support ranges for file hunks only */
|
||||
|| r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY
|
||||
|| r->headers_in.range == NULL
|
||||
|| r->headers_in.range->value.len < 7
|
||||
|| ngx_strncasecmp(r->headers_in.range->value.data, "bytes=", 6) != 0)
|
||||
{
|
||||
return next_header_filter(r);
|
||||
}
|
||||
|
||||
ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t),
|
||||
NGX_ERROR);
|
||||
|
||||
rc = 0;
|
||||
p = r->headers_in.range->value.data + 6;
|
||||
|
||||
for ( ;; ) {
|
||||
start = end = 0;
|
||||
|
||||
while (*p == ' ') { p++; }
|
||||
|
||||
if (*p < '0' || *p > '9') {
|
||||
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
start = start * 10 + *p++ - '0';
|
||||
}
|
||||
|
||||
while (*p == ' ') { p++; }
|
||||
|
||||
if (*p++ != '-') {
|
||||
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (start >= r->headers_out.content_length) {
|
||||
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
while (*p == ' ') { p++; }
|
||||
|
||||
if (*p == ',' || *p == '\0') {
|
||||
ngx_test_null(range, ngx_push_array(&r->headers_out.ranges),
|
||||
NGX_ERROR);
|
||||
range->start = start;
|
||||
range->end = r->headers_out.content_length;
|
||||
|
||||
if (*p++ == ',') {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p < '0' || *p > '9') {
|
||||
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
while (*p >= '0' && *p <= '9') {
|
||||
end = end * 10 + *p++ - '0';
|
||||
}
|
||||
|
||||
while (*p == ' ') { p++; }
|
||||
|
||||
if (*p != ',' && *p != '\0') {
|
||||
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (end >= r->headers_out.content_length || start >= end) {
|
||||
rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_test_null(range, ngx_push_array(&r->headers_out.ranges), NGX_ERROR);
|
||||
range->start = start;
|
||||
range->end = end + 1;
|
||||
|
||||
if (*p++ == ',') {
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
r->headers_out.status = rc;
|
||||
r->headers_out.ranges.nelts = 0;
|
||||
|
||||
ngx_test_null(r->headers_out.content_range,
|
||||
ngx_push_table(r->headers_out.headers),
|
||||
NGX_ERROR);
|
||||
|
||||
ngx_test_null(r->headers_out.content_range->value.data,
|
||||
ngx_palloc(r->pool, 8 + 20 + 1),
|
||||
NGX_ERROR);
|
||||
|
||||
r->headers_out.content_range->value.len =
|
||||
ngx_snprintf(r->headers_out.content_range->value.data,
|
||||
8 + 20 + 1, "bytes */" OFF_FMT,
|
||||
r->headers_out.content_length);
|
||||
|
||||
r->headers_out.content_length = -1;
|
||||
|
||||
return rc;
|
||||
|
||||
} else {
|
||||
r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
|
||||
|
||||
if (r->headers_out.ranges.nelts == 1) {
|
||||
ngx_test_null(r->headers_out.content_range,
|
||||
ngx_push_table(r->headers_out.headers),
|
||||
NGX_ERROR);
|
||||
|
||||
ngx_test_null(r->headers_out.content_range->value.data,
|
||||
ngx_palloc(r->pool, 6 + 20 + 1 + 20 + 1 + 20 + 1),
|
||||
NGX_ERROR);
|
||||
|
||||
r->headers_out.content_range->value.len =
|
||||
ngx_snprintf(r->headers_out.content_range->value.data,
|
||||
6 + 20 + 1 + 20 + 1 + 20 + 1,
|
||||
"bytes " OFF_FMT "-" OFF_FMT "/" OFF_FMT,
|
||||
range->start, range->end - 1,
|
||||
r->headers_out.content_length);
|
||||
|
||||
r->headers_out.content_length = range->end - range->start;
|
||||
|
||||
} else {
|
||||
|
||||
#if 0
|
||||
/* TODO: what if no content_type ?? */
|
||||
ngx_test_null(r->headers_out.content_type,
|
||||
ngx_push_table(r->headers_out.headers),
|
||||
NGX_ERROR);
|
||||
#endif
|
||||
|
||||
ngx_http_create_ctx(r, ctx, ngx_http_range_filter_module,
|
||||
sizeof(ngx_http_range_filter_ctx_t), NGX_ERROR);
|
||||
|
||||
len = 4 + 10 + 2 + 14 + r->headers_out.content_type->value.len
|
||||
+ 2 + 21 + 1;
|
||||
|
||||
if (r->headers_out.charset.len) {
|
||||
len += 10 + r->headers_out.charset.len;
|
||||
}
|
||||
|
||||
ngx_test_null(ctx->boundary_header.data, ngx_palloc(r->pool, len),
|
||||
NGX_ERROR);
|
||||
|
||||
boundary = ngx_next_temp_number(0);
|
||||
|
||||
if (r->headers_out.charset.len) {
|
||||
ctx->boundary_header.len =
|
||||
ngx_snprintf(ctx->boundary_header.data, len,
|
||||
CRLF "--%010u" CRLF
|
||||
"Content-Type: %s; charset=%s" CRLF
|
||||
"Content-Range: bytes ",
|
||||
boundary,
|
||||
r->headers_out.content_type->value.data,
|
||||
r->headers_out.charset.data);
|
||||
|
||||
r->headers_out.charset.len = 0;
|
||||
|
||||
} else {
|
||||
ctx->boundary_header.len =
|
||||
ngx_snprintf(ctx->boundary_header.data, len,
|
||||
CRLF "--%010u" CRLF
|
||||
"Content-Type: %s" CRLF
|
||||
"Content-Range: bytes ",
|
||||
boundary,
|
||||
r->headers_out.content_type->value.data);
|
||||
}
|
||||
|
||||
ngx_test_null(r->headers_out.content_type->value.data,
|
||||
ngx_palloc(r->pool, 31 + 10 + 1),
|
||||
NGX_ERROR);
|
||||
|
||||
r->headers_out.content_type->value.len =
|
||||
ngx_snprintf(r->headers_out.content_type->value.data,
|
||||
31 + 10 + 1,
|
||||
"multipart/byteranges; boundary=%010u",
|
||||
boundary);
|
||||
|
||||
/* the last "CRLF--BOUNDARY--CRLF" */
|
||||
len = 4 + 10 + 4;
|
||||
|
||||
range = r->headers_out.ranges.elts;
|
||||
for (i = 0; i < r->headers_out.ranges.nelts; i++) {
|
||||
ngx_test_null(range[i].content_range.data,
|
||||
ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5),
|
||||
NGX_ERROR);
|
||||
|
||||
range[i].content_range.len =
|
||||
ngx_snprintf(range[i].content_range.data,
|
||||
20 + 1 + 20 + 1 + 20 + 5,
|
||||
OFF_FMT "-" OFF_FMT "/" OFF_FMT CRLF CRLF,
|
||||
range[i].start, range[i].end - 1,
|
||||
r->headers_out.content_length);
|
||||
|
||||
len += ctx->boundary_header.len + range[i].content_range.len
|
||||
+ range[i].end - range[i].start;
|
||||
}
|
||||
|
||||
r->headers_out.content_length = len;
|
||||
}
|
||||
}
|
||||
|
||||
return next_header_filter(r);
|
||||
}
|
||||
|
||||
|
||||
static int ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
{
|
||||
int i;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t *out, *hce, *rce, *dce, **le;
|
||||
ngx_http_range_t *range;
|
||||
ngx_http_range_filter_ctx_t *ctx;
|
||||
|
||||
if (r->headers_out.ranges.nelts == 0) {
|
||||
return next_body_filter(r, in);
|
||||
}
|
||||
|
||||
/* the optimized version for the static files only
|
||||
that are passed in the single file hunk */
|
||||
|
||||
if (in
|
||||
&& in->hunk->type & NGX_HUNK_FILE
|
||||
&& in->hunk->type & NGX_HUNK_LAST)
|
||||
{
|
||||
if (r->headers_out.ranges.nelts == 1) {
|
||||
range = r->headers_out.ranges.elts;
|
||||
in->hunk->file_pos = range->start;
|
||||
in->hunk->file_last = range->end;
|
||||
|
||||
return next_body_filter(r, in);
|
||||
}
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_range_filter_module);
|
||||
le = &out;
|
||||
|
||||
range = r->headers_out.ranges.elts;
|
||||
for (i = 0; i < r->headers_out.ranges.nelts; i++) {
|
||||
|
||||
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
|
||||
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_MEMORY;
|
||||
h->pos = ctx->boundary_header.data;
|
||||
h->last = ctx->boundary_header.data + ctx->boundary_header.len;
|
||||
|
||||
ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
hce->hunk = h;
|
||||
|
||||
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
|
||||
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP;
|
||||
h->pos = range[i].content_range.data;
|
||||
h->last = range[i].content_range.data + range[i].content_range.len;
|
||||
|
||||
ngx_test_null(rce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
rce->hunk = h;
|
||||
|
||||
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
|
||||
h->type = NGX_HUNK_FILE;
|
||||
h->file_pos = range[i].start;
|
||||
h->file_last = range[i].end;
|
||||
h->file = in->hunk->file;
|
||||
|
||||
ngx_test_null(dce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
dce->hunk = h;
|
||||
dce->next = NULL;
|
||||
|
||||
*le = hce;
|
||||
hce->next = rce;
|
||||
rce->next = dce;
|
||||
le = &dce->next;
|
||||
}
|
||||
|
||||
ngx_test_null(h, ngx_calloc_hunk(r->pool), NGX_ERROR);
|
||||
h->type = NGX_HUNK_IN_MEMORY|NGX_HUNK_TEMP|NGX_HUNK_LAST;
|
||||
ngx_test_null(h->pos, ngx_palloc(r->pool, 4 + 10 + 4), NGX_ERROR);
|
||||
h->last = ngx_cpymem(h->pos, ctx->boundary_header.data, 4 + 10);
|
||||
*h->last++ = '-'; *h->last++ = '-';
|
||||
*h->last++ = CR; *h->last++ = LF;
|
||||
|
||||
ngx_test_null(hce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
hce->hunk = h;
|
||||
hce->next = NULL;
|
||||
*le = hce;
|
||||
|
||||
return next_body_filter(r, out);
|
||||
}
|
||||
|
||||
/* TODO: several incoming hunks of proxied responses
|
||||
and memory hunks on platforms that have no sendfile() */
|
||||
|
||||
return next_body_filter(r, in);
|
||||
}
|
||||
|
||||
|
||||
static int ngx_http_range_filter_init(ngx_pool_t *pool)
|
||||
{
|
||||
next_header_filter = ngx_http_top_header_filter;
|
||||
ngx_http_top_header_filter = ngx_http_range_header_filter;
|
||||
|
||||
next_body_filter = ngx_http_top_body_filter;
|
||||
ngx_http_top_body_filter = ngx_http_range_body_filter;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
@ -2,10 +2,6 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_config.h>
|
||||
#include <ngx_http_core_module.h>
|
||||
#include <ngx_http_output_filter.h>
|
||||
|
||||
|
||||
|
||||
int ngx_http_static_handler(ngx_http_request_t *r)
|
||||
@ -32,7 +28,8 @@ int ngx_http_static_handler(ngx_http_request_t *r)
|
||||
ctx->action = "sending response";
|
||||
|
||||
if (r->file.fd == NGX_INVALID_FILE) {
|
||||
r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY);
|
||||
r->file.fd = ngx_open_file(r->file.name.data,
|
||||
NGX_FILE_RDONLY, NGX_FILE_OPEN);
|
||||
|
||||
if (r->file.fd == NGX_INVALID_FILE) {
|
||||
err = ngx_errno;
|
||||
@ -129,6 +126,10 @@ int ngx_http_static_handler(ngx_http_request_t *r)
|
||||
|
||||
|
||||
rc = ngx_http_send_header(r);
|
||||
if (rc == NGX_ERROR || rc > NGX_OK) {
|
||||
ngx_http_finalize_request(r, rc);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (r->header_only) {
|
||||
if (rc == NGX_AGAIN) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <ngx_http_request.h>
|
||||
#include <ngx_http_config.h>
|
||||
#include <ngx_http_filter.h>
|
||||
#include <ngx_http_core_module.h>
|
||||
|
||||
|
||||
|
@ -1,5 +1,12 @@
|
||||
|
||||
|
||||
/*
|
||||
* small file in malloc()ed memory, mmap()ed file, file descriptor only,
|
||||
* file access time only (to estimate can pages pages still be in memory),
|
||||
* translated URI (ngx_http_index_hanlder),
|
||||
* compiled script (ngx_http_ssi_filter).
|
||||
*/
|
||||
|
||||
|
||||
#define NGX_HTTP_CACHE_ENTRY_DELETED 0x00000001
|
||||
#define NGX_HTTP_CACHE_ENTRY_MMAPED 0x00000002
|
||||
@ -7,6 +14,9 @@
|
||||
/* "/" -> "/index.html" in ngx_http_index_handler */
|
||||
#define NGX_HTTP_CACHE_ENTRY_URI 0x00000004
|
||||
|
||||
/* complied script */
|
||||
#define NGX_HTTP_CACHE_ENTRY_SCRIPT 0x00000008
|
||||
|
||||
#define NGX_HTTP_CACHE_FILTER_FLAGS 0xFFFF0000
|
||||
|
||||
|
||||
@ -42,7 +52,7 @@ int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash,
|
||||
int hi;
|
||||
ngx_http_cache_hash_entry_t *entry;
|
||||
|
||||
h->crc = ngx_crc32(uri->data, uri->len);
|
||||
h->crc = ngx_crc(uri->data, uri->len);
|
||||
|
||||
hi = h->crc % cache_hash->size;
|
||||
entry = cache_hash[hi].elts;
|
||||
@ -61,3 +71,23 @@ int ngx_http_cache_get(ngx_http_cache_hash_t *cache_hash,
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* 32-bit crc16 */
|
||||
|
||||
int ngx_crc(char *data, size_t len)
|
||||
{
|
||||
u_int32_t sum;
|
||||
|
||||
for (sum = 0; len; len--) {
|
||||
/*
|
||||
* gcc 2.95.2 x86 compiles that operator into the single rol opcode.
|
||||
* msvc 6.0sp2 compiles it into four opcodes.
|
||||
*/
|
||||
sum = sum >> 1 | sum << 31;
|
||||
|
||||
sum += *data++;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
@ -6,8 +6,6 @@
|
||||
#include <ngx_listen.h>
|
||||
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_output_filter.h>
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
@ -97,14 +95,18 @@ static ngx_command_t ngx_http_core_commands[] = {
|
||||
NULL},
|
||||
|
||||
{ngx_string("listen"),
|
||||
#if 0
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
#else
|
||||
NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
||||
#endif
|
||||
ngx_set_listen,
|
||||
NGX_HTTP_SRV_CONF_OFFSET,
|
||||
0,
|
||||
NULL},
|
||||
|
||||
{ngx_string("server_name"),
|
||||
NGX_HTTP_SRV_CONF|NGX_CONF_ANY1,
|
||||
NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
|
||||
ngx_set_server_name,
|
||||
NGX_HTTP_SRV_CONF_OFFSET,
|
||||
0,
|
||||
@ -195,12 +197,16 @@ ngx_module_t ngx_http_core_module = {
|
||||
void ngx_http_handler(ngx_http_request_t *r)
|
||||
{
|
||||
int rc, i;
|
||||
ngx_http_log_ctx_t *lcx;
|
||||
ngx_http_handler_pt *h;
|
||||
ngx_http_core_loc_conf_t *clcf, **clcfp;
|
||||
ngx_http_core_srv_conf_t *cscf;
|
||||
|
||||
r->connection->unexpected_eof = 0;
|
||||
|
||||
lcx = r->connection->log->data;
|
||||
lcx->action = NULL;
|
||||
|
||||
r->keepalive = 1;
|
||||
|
||||
if (r->headers_in.content_length_n > 0) {
|
||||
@ -337,7 +343,8 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
|
||||
#else
|
||||
|
||||
if (r->file.fd == NGX_INVALID_FILE) {
|
||||
r->file.fd = ngx_open_file(r->file.name.data, NGX_FILE_RDONLY);
|
||||
r->file.fd = ngx_open_file(r->file.name.data,
|
||||
NGX_FILE_RDONLY, NGX_FILE_OPEN);
|
||||
}
|
||||
|
||||
if (r->file.fd == NGX_INVALID_FILE) {
|
||||
@ -367,6 +374,8 @@ ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->file.name.data);
|
||||
r->file.name.data);
|
||||
}
|
||||
|
||||
r->file.fd = NGX_INVALID_FILE;
|
||||
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
@ -382,6 +391,8 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
|
||||
ngx_close_file_n " \"%s\" failed", r->file.name.data);
|
||||
}
|
||||
|
||||
r->file.fd = NGX_INVALID_FILE;
|
||||
#endif
|
||||
|
||||
/* BROKEN: need to include server name */
|
||||
@ -782,12 +793,13 @@ static char *ngx_http_core_merge_srv_conf(ngx_pool_t *pool,
|
||||
ngx_http_listen_t *l;
|
||||
ngx_http_server_name_t *n;
|
||||
|
||||
/* TODO: it does not merge, it init only */
|
||||
/* TODO: it does not merge, it inits only */
|
||||
|
||||
if (conf->listen.nelts == 0) {
|
||||
ngx_test_null(l, ngx_push_array(&conf->listen), NGX_CONF_ERROR);
|
||||
l->addr = INADDR_ANY;
|
||||
l->port = 8000;
|
||||
/* STUB: getuid() should be cached */
|
||||
l->port = (getuid() == 0) ? 80 : 8000;
|
||||
l->family = AF_INET;
|
||||
}
|
||||
|
||||
@ -871,8 +883,7 @@ static char *ngx_http_core_merge_loc_conf(ngx_pool_t *pool,
|
||||
int i, key;
|
||||
ngx_http_type_t *t;
|
||||
|
||||
ngx_conf_merge_str_value(conf->doc_root,
|
||||
prev->doc_root, "html");
|
||||
ngx_conf_merge_str_value(conf->doc_root, prev->doc_root, "html");
|
||||
|
||||
if (conf->types == NULL) {
|
||||
if (prev->types) {
|
||||
|
@ -1,21 +1,8 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_string.h>
|
||||
#include <ngx_files.h>
|
||||
#include <ngx_log.h>
|
||||
#include <ngx_alloc.h>
|
||||
#include <ngx_array.h>
|
||||
#include <ngx_table.h>
|
||||
#include <ngx_hunk.h>
|
||||
#include <ngx_connection.h>
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_event_timer.h>
|
||||
#include <ngx_inet.h>
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_config.h>
|
||||
#include <ngx_http_core_module.h>
|
||||
#include <ngx_http_output_filter.h>
|
||||
|
||||
|
||||
static void ngx_http_init_request(ngx_event_t *ev);
|
||||
@ -63,12 +50,13 @@ static ngx_http_header_t headers_in[] = {
|
||||
{ ngx_string("Content-Length"),
|
||||
offsetof(ngx_http_headers_in_t, content_length) },
|
||||
|
||||
{ ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) },
|
||||
#if 0
|
||||
{ ngx_string("If-Range"), offsetof(ngx_http_headers_in_t, if_range) },
|
||||
#endif
|
||||
|
||||
{ ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
|
||||
|
||||
#endif
|
||||
|
||||
{ ngx_null_string, 0 }
|
||||
};
|
||||
|
||||
@ -289,6 +277,13 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
|
||||
|
||||
/* the request line has been parsed successfully */
|
||||
|
||||
/* STUB: we need to handle such URIs */
|
||||
if (r->complex_uri || r->unusual_uri) {
|
||||
ngx_http_header_parse_error(r, NGX_HTTP_PARSE_INVALID_REQUEST);
|
||||
ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||
|
||||
if (r->http_version >= NGX_HTTP_VERSION_10
|
||||
@ -402,7 +397,7 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
|
||||
if (r->args.data[0] == '\0') { r->args.data = NULL; }
|
||||
#endif
|
||||
|
||||
if (r->http_version == NGX_HTTP_VERSION_9) {
|
||||
if (r->http_version < NGX_HTTP_VERSION_10) {
|
||||
rev->event_handler = ngx_http_block_read;
|
||||
ngx_http_handler(r);
|
||||
return;
|
||||
@ -1436,9 +1431,14 @@ static size_t ngx_http_log_error(void *data, char *buf, size_t len)
|
||||
{
|
||||
ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data;
|
||||
|
||||
if (ctx->url) {
|
||||
if (ctx->action && ctx->url) {
|
||||
return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
|
||||
ctx->action, ctx->client, ctx->url);
|
||||
|
||||
} else if (ctx->action == NULL && ctx->url) {
|
||||
return ngx_snprintf(buf, len, ", client: %s, URL: %s",
|
||||
ctx->client, ctx->url);
|
||||
|
||||
} else {
|
||||
return ngx_snprintf(buf, len, " while %s, client: %s",
|
||||
ctx->action, ctx->client);
|
||||
|
18
src/http/ngx_http_filter.h
Normal file
18
src/http/ngx_http_filter.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef _NGX_HTTP_FILTER_H_INCLUDED_
|
||||
#define _NGX_HTTP_FILTER_H_INCLUDED_
|
||||
|
||||
|
||||
#define NGX_HTTP_FILTER_NEED_IN_MEMORY 1
|
||||
#define NGX_HTTP_FILTER_SSI_NEED_IN_MEMORY 2
|
||||
#define NGX_HTTP_FILTER_NEED_TEMP 4
|
||||
|
||||
|
||||
int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk);
|
||||
int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
|
||||
|
||||
|
||||
extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
|
||||
extern int (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_FILTER_H_INCLUDED_ */
|
@ -1,8 +1,6 @@
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_types.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
size_t ngx_http_get_time(char *buf, time_t t)
|
||||
|
@ -1,11 +1,8 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_write_filter.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
static int ngx_http_header_filter_init(ngx_pool_t *pool);
|
||||
@ -52,7 +49,11 @@ static ngx_str_t http_codes[] = {
|
||||
#endif
|
||||
|
||||
ngx_string("301 Moved Permanently"),
|
||||
#if 0
|
||||
ngx_string("302 Moved Temporarily"),
|
||||
#else
|
||||
ngx_string("302 Found"),
|
||||
#endif
|
||||
ngx_null_string, /* "303 See Other" */
|
||||
ngx_string("304 Not Modified"),
|
||||
|
||||
@ -87,11 +88,12 @@ static ngx_str_t http_codes[] = {
|
||||
|
||||
static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
int len, status, text, i;
|
||||
time_t ims;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t *ch;
|
||||
ngx_table_elt_t *header;
|
||||
int len, status, i;
|
||||
time_t ims;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t *ch;
|
||||
ngx_table_elt_t *header;
|
||||
ngx_http_range_t *range;
|
||||
|
||||
if (r->http_version < NGX_HTTP_VERSION_10) {
|
||||
return NGX_OK;
|
||||
@ -170,20 +172,23 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
len += 37;
|
||||
}
|
||||
|
||||
if (r->headers_out.content_range && r->headers_out.content_range->value.len)
|
||||
{
|
||||
len += 15 + r->headers_out.content_range->value.len + 2;
|
||||
}
|
||||
|
||||
if (r->headers_out.content_length >= 0) {
|
||||
/* "Content-Length: ... \r\n", 2^64 is 20 characters */
|
||||
len += 48;
|
||||
}
|
||||
|
||||
text = 0;
|
||||
if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
|
||||
r->headers_out.content_type->key.len = 0;
|
||||
len += 16 + r->headers_out.content_type->value.len;
|
||||
if (ngx_strncasecmp(r->headers_out.content_type->value.data,
|
||||
"text/", 5) == 0) {
|
||||
text = 1;
|
||||
/* "; charset=koi8-r" */
|
||||
len += 16;
|
||||
|
||||
if (r->headers_out.charset.len) {
|
||||
/* "; charset= ... " */
|
||||
len += 10 + r->headers_out.charset.len;
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,6 +215,11 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
len += 46;
|
||||
}
|
||||
|
||||
if (r->chunked) {
|
||||
/* "Transfer-Encoding: chunked\r\n" */
|
||||
len += 28;
|
||||
}
|
||||
|
||||
if (r->keepalive == 0) {
|
||||
/* "Connection: close\r\n" */
|
||||
len += 19;
|
||||
@ -253,6 +263,15 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
|
||||
if (r->headers_out.content_range && r->headers_out.content_range->value.len)
|
||||
{
|
||||
h->last = ngx_cpymem(h->last, "Content-Range: ", 15);
|
||||
h->last = ngx_cpymem(h->last, r->headers_out.content_range->value.data,
|
||||
r->headers_out.content_range->value.len);
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
/* 2^64 is 20 characters */
|
||||
if (r->headers_out.content_length >= 0) {
|
||||
h->last += ngx_snprintf(h->last, 49,
|
||||
@ -263,10 +282,12 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
|
||||
h->last = ngx_cpymem(h->last, "Content-Type: ", 14);
|
||||
h->last = ngx_cpymem(h->last, r->headers_out.content_type->value.data,
|
||||
r->headers_out.content_type->value.len);
|
||||
r->headers_out.content_type->value.len);
|
||||
|
||||
if (text) {
|
||||
h->last = ngx_cpymem(h->last, "; charset=koi8-r", 16);
|
||||
if (r->headers_out.charset.len) {
|
||||
h->last = ngx_cpymem(h->last, "; charset=", 10);
|
||||
h->last = ngx_cpymem(h->last, r->headers_out.charset.data,
|
||||
r->headers_out.charset.len);
|
||||
}
|
||||
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
@ -299,6 +320,10 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
if (r->chunked) {
|
||||
h->last = ngx_cpymem(h->last, "Transfer-Encoding: chunked" CRLF, 28);
|
||||
}
|
||||
|
||||
if (r->keepalive == 0) {
|
||||
h->last = ngx_cpymem(h->last, "Connection: close" CRLF, 19);
|
||||
|
||||
|
@ -1,15 +1,20 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_files.h>
|
||||
#include <ngx_string.h>
|
||||
#include <ngx_hunk.h>
|
||||
#include <ngx_conf_file.h>
|
||||
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_config.h>
|
||||
#include <ngx_http_output_filter.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t hunk_size;
|
||||
} ngx_http_output_filter_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_hunk_t *hunk; /* the temporary hunk to copy */
|
||||
ngx_chain_t *incoming;
|
||||
ngx_chain_t in; /* one chain entry for input */
|
||||
ngx_chain_t out; /* one chain entry for output */
|
||||
} ngx_http_output_filter_ctx_t;
|
||||
|
||||
|
||||
static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src);
|
||||
|
@ -1,34 +0,0 @@
|
||||
#ifndef _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_
|
||||
#define _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_hunk.h>
|
||||
#include <ngx_conf_file.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#define NGX_HTTP_FILTER_NEED_IN_MEMORY 1
|
||||
#define NGX_HTTP_FILTER_SSI_NEED_IN_MEMORY 2
|
||||
#define NGX_HTTP_FILTER_NEED_TEMP 4
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t hunk_size;
|
||||
} ngx_http_output_filter_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_hunk_t *hunk; /* the temporary hunk to copy */
|
||||
ngx_chain_t *incoming;
|
||||
ngx_chain_t in; /* one chain entry for input */
|
||||
ngx_chain_t out; /* one chain entry for output */
|
||||
} ngx_http_output_filter_ctx_t;
|
||||
|
||||
|
||||
int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk);
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_output_filter_module;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_OUTPUT_FILTER_H_INCLUDED_ */
|
@ -175,7 +175,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
|
||||
}
|
||||
break;
|
||||
|
||||
/* check "/." or "//" */
|
||||
/* check "/.", "//", and "%" in URI */
|
||||
case sw_after_slash_in_uri:
|
||||
switch (ch) {
|
||||
case CR:
|
||||
@ -193,6 +193,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
|
||||
state = sw_http_09;
|
||||
break;
|
||||
case '.':
|
||||
case '%':
|
||||
r->complex_uri = 1;
|
||||
state = sw_uri;
|
||||
break;
|
||||
@ -211,7 +212,7 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
|
||||
}
|
||||
break;
|
||||
|
||||
/* check slash in URI */
|
||||
/* check "/" and "%" in URI */
|
||||
case sw_check_uri:
|
||||
switch (ch) {
|
||||
case CR:
|
||||
@ -235,6 +236,10 @@ int ngx_parse_http_request_line(ngx_http_request_t *r)
|
||||
r->uri_ext = NULL;
|
||||
state = sw_after_slash_in_uri;
|
||||
break;
|
||||
case '%':
|
||||
r->complex_uri = 1;
|
||||
state = sw_uri;
|
||||
break;
|
||||
case '?':
|
||||
r->args_start = p;
|
||||
state = sw_uri;
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
|
||||
#define NGX_HTTP_OK 200
|
||||
#define NGX_HTTP_PARTIAL_CONTENT 206
|
||||
|
||||
#define NGX_HTTP_SPECIAL_RESPONSE 300
|
||||
#define NGX_HTTP_MOVED_PERMANENTLY 301
|
||||
@ -52,6 +53,7 @@
|
||||
#define NGX_HTTP_NOT_ALLOWED 405
|
||||
#define NGX_HTTP_REQUEST_TIME_OUT 408
|
||||
#define NGX_HTTP_REQUEST_URI_TOO_LARGE 414
|
||||
#define NGX_HTTP_RANGE_NOT_SATISFIABLE 416
|
||||
|
||||
#define NGX_HTTP_INTERNAL_SERVER_ERROR 500
|
||||
#define NGX_HTTP_NOT_IMPLEMENTED 501
|
||||
@ -79,6 +81,8 @@ typedef struct {
|
||||
ngx_table_elt_t *connection;
|
||||
ngx_table_elt_t *if_modified_since;
|
||||
ngx_table_elt_t *content_length;
|
||||
ngx_table_elt_t *range;
|
||||
|
||||
ngx_table_elt_t *accept_encoding;
|
||||
|
||||
ngx_table_elt_t *user_agent;
|
||||
@ -99,6 +103,13 @@ typedef struct {
|
||||
} ngx_http_request_body_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
off_t start;
|
||||
off_t end;
|
||||
ngx_str_t content_range;
|
||||
} ngx_http_range_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int status;
|
||||
ngx_str_t status_line;
|
||||
@ -108,11 +119,14 @@ typedef struct {
|
||||
ngx_table_elt_t *content_type;
|
||||
ngx_table_elt_t *location;
|
||||
ngx_table_elt_t *last_modified;
|
||||
ngx_table_elt_t *content_range;
|
||||
|
||||
ngx_str_t charset;
|
||||
ngx_array_t ranges;
|
||||
|
||||
ngx_table_t *headers;
|
||||
|
||||
off_t content_length;
|
||||
char *charset;
|
||||
char *etag;
|
||||
time_t date_time;
|
||||
time_t last_modified_time;
|
||||
@ -140,7 +154,7 @@ struct ngx_http_request_s {
|
||||
|
||||
int (*handler)(ngx_http_request_t *r);
|
||||
|
||||
time_t lingering_time;
|
||||
time_t lingering_time;
|
||||
|
||||
int method;
|
||||
int http_version;
|
||||
@ -161,46 +175,44 @@ struct ngx_http_request_s {
|
||||
ngx_str_t *server_name;
|
||||
ngx_array_t *virtual_names;
|
||||
|
||||
int filter;
|
||||
|
||||
char *discarded_buffer;
|
||||
char *discarded_buffer;
|
||||
|
||||
ngx_str_t path;
|
||||
int path_err;
|
||||
ngx_str_t path;
|
||||
int path_err;
|
||||
|
||||
unsigned proxy:1;
|
||||
unsigned cachable:1;
|
||||
unsigned pipeline:1;
|
||||
unsigned keepalive:1;
|
||||
unsigned lingering_close:1;
|
||||
/* URI is not started with '/' - "GET http://" */
|
||||
unsigned unusual_uri:1;
|
||||
/* URI with "/.", "%" and on Win32 with "//" */
|
||||
unsigned complex_uri:1;
|
||||
unsigned header_timeout_set:1;
|
||||
|
||||
unsigned header_read:1;
|
||||
unsigned header_timeout_set:1;
|
||||
|
||||
unsigned logging:1;
|
||||
|
||||
unsigned header_only:1;
|
||||
unsigned unusual_uri:1; /* URI is not started with '/' - "GET http://" */
|
||||
unsigned complex_uri:1; /* URI with "/." or with "//" (WIN32) */
|
||||
unsigned path_not_found:1;
|
||||
#ifdef NGX_EVENT
|
||||
unsigned write_level_event:1;
|
||||
unsigned proxy:1;
|
||||
#if 0
|
||||
unsigned cachable:1;
|
||||
#endif
|
||||
unsigned pipeline:1;
|
||||
|
||||
int state;
|
||||
char *uri_start;
|
||||
char *uri_end;
|
||||
char *uri_ext;
|
||||
char *args_start;
|
||||
char *request_start;
|
||||
char *request_end;
|
||||
char *header_name_start;
|
||||
char *header_name_end;
|
||||
char *header_start;
|
||||
char *header_end;
|
||||
#ifdef NGX_EVENT
|
||||
int (*state_handler)(ngx_http_request_t *r);
|
||||
#endif
|
||||
unsigned chunked:1;
|
||||
unsigned header_only:1;
|
||||
unsigned keepalive:1;
|
||||
unsigned lingering_close:1;
|
||||
|
||||
/* TODO: use filter or bits ???? */
|
||||
int filter;
|
||||
|
||||
/* used to parse HTTP headers */
|
||||
int state;
|
||||
char *uri_start;
|
||||
char *uri_end;
|
||||
char *uri_ext;
|
||||
char *args_start;
|
||||
char *request_start;
|
||||
char *request_end;
|
||||
char *header_name_start;
|
||||
char *header_name_end;
|
||||
char *header_start;
|
||||
char *header_end;
|
||||
};
|
||||
|
||||
|
||||
|
49
src/http/ngx_http_script.c
Normal file
49
src/http/ngx_http_script.c
Normal file
@ -0,0 +1,49 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
char *ngx_http_script_copy(ngx_http_request_t *r,
|
||||
ngx_http_script_code_t *code,
|
||||
char *p, size_t len)
|
||||
{
|
||||
return ngx_cpymem(p, code->offset, code->len < len ? code->len : len);
|
||||
}
|
||||
|
||||
|
||||
char *ngx_http_script_header_in(ngx_http_request_t *r,
|
||||
ngx_http_script_code_t *code,
|
||||
char *p, size_t len)
|
||||
{
|
||||
ngx_str_t *s;
|
||||
|
||||
s = (ngx_str_t *) (((char *) r->headers_in) + code->offset);
|
||||
|
||||
return ngx_cpymem(p, s->data, s->len < len ? s->len : len);
|
||||
}
|
||||
|
||||
|
||||
/* the log script codes */
|
||||
|
||||
char *ngx_http_script_request_line(ngx_http_request_t *r, char *p, size_t len)
|
||||
{
|
||||
return ngx_cpymem(p, r->request_line.data,
|
||||
r->request_line.len < len ? r->request_line.len : len);
|
||||
}
|
||||
|
||||
|
||||
char *ngx_http_script_status(ngx_http_request_t *r, char *p, size_t len)
|
||||
{
|
||||
p += ngx_snprintf(p, len, "%d", r->headers_out.status);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
char *ngx_http_script_sent(ngx_http_request_t *r, char *p, size_t len)
|
||||
{
|
||||
p += ngx_snprintf(p, len, OFF_FMT, r->connection->sent);
|
||||
|
||||
return p;
|
||||
}
|
12
src/http/ngx_http_script.h
Normal file
12
src/http/ngx_http_script.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _NGX_HTTP_SCRIPT_H_INCLUDED_
|
||||
#define _NGX_HTTP_SCRIPT_H_INCLUDED_
|
||||
|
||||
|
||||
typedef struct {
|
||||
handler;
|
||||
offset / data;
|
||||
size;
|
||||
} ngx_http_script_code_t;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_SCRIPT_H_INCLUDED_ */
|
@ -1,11 +1,8 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
#include <nginx.h>
|
||||
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_output_filter.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
static char error_tail[] =
|
||||
@ -15,6 +12,14 @@ static char error_tail[] =
|
||||
;
|
||||
|
||||
|
||||
static char error_302_page[] =
|
||||
"<html>" CRLF
|
||||
"<head><title>302 Found</title></head>" CRLF
|
||||
"<body bgcolor=\"white\">" CRLF
|
||||
"<center><h1>302 Found</h1></center>" CRLF
|
||||
;
|
||||
|
||||
|
||||
static char error_400_page[] =
|
||||
"<html>" CRLF
|
||||
"<head><title>400 Bad Request</title></head>" CRLF
|
||||
@ -63,6 +68,14 @@ static char error_414_page[] =
|
||||
;
|
||||
|
||||
|
||||
static char error_416_page[] =
|
||||
"<html>" CRLF
|
||||
"<head><title>416 Requested Range Not Satisfiable</title></head>" CRLF
|
||||
"<body bgcolor=\"white\">" CRLF
|
||||
"<center><h1>416 Requested Range Not Satisfiable</h1></center>" CRLF
|
||||
;
|
||||
|
||||
|
||||
static char error_500_page[] =
|
||||
"<html>" CRLF
|
||||
"<head><title>500 Internal Server Error</title></head>" CRLF
|
||||
@ -88,8 +101,9 @@ static char error_504_page[] =
|
||||
|
||||
|
||||
static ngx_str_t error_pages[] = {
|
||||
ngx_null_string, /* 300 */
|
||||
ngx_null_string, /* 301 */
|
||||
ngx_null_string, /* 302 */
|
||||
ngx_string(error_302_page),
|
||||
ngx_null_string, /* 303 */
|
||||
|
||||
ngx_string(error_400_page),
|
||||
@ -108,7 +122,7 @@ static ngx_str_t error_pages[] = {
|
||||
ngx_null_string, /* 413 */
|
||||
ngx_string(error_414_page),
|
||||
ngx_null_string, /* 415 */
|
||||
ngx_null_string, /* 416 */
|
||||
ngx_string(error_416_page),
|
||||
|
||||
ngx_string(error_500_page),
|
||||
ngx_null_string, /* 501 */
|
||||
@ -120,35 +134,22 @@ static ngx_str_t error_pages[] = {
|
||||
|
||||
int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
|
||||
{
|
||||
int err, len;
|
||||
int err;
|
||||
ngx_hunk_t *message, *tail;
|
||||
|
||||
len = 0;
|
||||
|
||||
r->headers_out.status = error;
|
||||
|
||||
if (error < NGX_HTTP_BAD_REQUEST) {
|
||||
/* 3XX */
|
||||
err = error - NGX_HTTP_MOVED_PERMANENTLY;
|
||||
|
||||
} else if (error < NGX_HTTP_INTERNAL_SERVER_ERROR) {
|
||||
/* 4XX */
|
||||
err = error - NGX_HTTP_BAD_REQUEST + 4;
|
||||
|
||||
} else {
|
||||
ngx_test_null(r->headers_out.content_type,
|
||||
ngx_push_table(r->headers_out.headers),
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
||||
r->headers_out.content_type->key.len = 12;
|
||||
r->headers_out.content_type->key.data = "Content-Type";
|
||||
r->headers_out.content_type->value.len = 9;
|
||||
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;
|
||||
}
|
||||
/* 5XX */
|
||||
err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 4 + 17;
|
||||
}
|
||||
|
||||
if (r->keepalive != 0) {
|
||||
@ -169,11 +170,21 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
|
||||
}
|
||||
}
|
||||
|
||||
if (error_pages[err].len == 0) {
|
||||
r->headers_out.content_length = -1;
|
||||
} else {
|
||||
if (error_pages[err].len) {
|
||||
r->headers_out.content_length = error_pages[err].len
|
||||
+ len + sizeof(error_tail);
|
||||
+ sizeof(error_tail);
|
||||
|
||||
ngx_test_null(r->headers_out.content_type,
|
||||
ngx_push_table(r->headers_out.headers),
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
||||
r->headers_out.content_type->key.len = 12;
|
||||
r->headers_out.content_type->key.data = "Content-Type";
|
||||
r->headers_out.content_type->value.len = 9;
|
||||
r->headers_out.content_type->value.data = "text/html";
|
||||
|
||||
} else {
|
||||
r->headers_out.content_length = -1;
|
||||
}
|
||||
|
||||
if (ngx_http_send_header(r) == NGX_ERROR) {
|
||||
|
@ -1,16 +1,17 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_hunk.h>
|
||||
#include <ngx_conf_file.h>
|
||||
#include <ngx_connection.h>
|
||||
|
||||
#include <ngx_event_write.h>
|
||||
|
||||
#include <ngx_http.h>
|
||||
#include <ngx_http_config.h>
|
||||
#include <ngx_http_write_filter.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t buffer_output;
|
||||
} ngx_http_write_filter_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_chain_t *out;
|
||||
} ngx_http_write_filter_ctx_t;
|
||||
|
||||
|
||||
static void *ngx_http_write_filter_create_conf(ngx_pool_t *pool);
|
||||
@ -96,7 +97,7 @@ int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
||||
/* add the new chain to the existent one */
|
||||
|
||||
for (/* void */; in; in = in->next) {
|
||||
ngx_test_null(ce, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR);
|
||||
ngx_test_null(ce, ngx_alloc_chain_entry(r->pool), NGX_ERROR);
|
||||
|
||||
ce->hunk = in->hunk;
|
||||
ce->next = NULL;
|
||||
|
@ -1,25 +0,0 @@
|
||||
#ifndef _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
|
||||
#define _NGX_HTTP_WRITE_FILTER_H_INCLUDED_
|
||||
|
||||
|
||||
#include <ngx_hunk.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t buffer_output;
|
||||
} ngx_http_write_filter_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_chain_t *out;
|
||||
} ngx_http_write_filter_ctx_t;
|
||||
|
||||
|
||||
int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in);
|
||||
|
||||
|
||||
extern ngx_module_t ngx_http_write_filter_module;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_WRITE_FILTER_H_INCLUDED_ */
|
@ -15,20 +15,29 @@
|
||||
|
||||
|
||||
|
||||
#define ngx_open_file open
|
||||
#define ngx_open_file(name, access, create) \
|
||||
open(name, access|create, 0644)
|
||||
#define ngx_open_file_n "open()"
|
||||
|
||||
#define NGX_FILE_RDONLY O_RDONLY
|
||||
#define NGX_FILE_RDWR O_RDWR
|
||||
#define NGX_FILE_CREATE_OR_OPEN O_CREAT
|
||||
#define NGX_FILE_OPEN 0
|
||||
#define NGX_FILE_APPEND O_APPEND
|
||||
|
||||
|
||||
#define ngx_close_file close
|
||||
#define ngx_close_file_n "close()"
|
||||
|
||||
|
||||
#define ngx_open_tempfile(name, persistent) \
|
||||
open(name, O_CREAT|O_EXCL|O_RDWR, 0600)
|
||||
#define ngx_open_tempfile_n "open()"
|
||||
|
||||
|
||||
ssize_t ngx_read_file(ngx_file_t *file, char *buf, size_t size, off_t offset);
|
||||
#define ngx_read_file_n "read()"
|
||||
|
||||
#define NGX_FILE_RDONLY O_RDONLY
|
||||
|
||||
ssize_t ngx_write_file(ngx_file_t *file, char *buf, size_t size, off_t offset);
|
||||
|
||||
|
@ -9,6 +9,7 @@ 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_freebsd_tcp_nopush_flush;
|
||||
|
||||
/* FreeBSD 5.0 */
|
||||
int ngx_freebsd_kern_ipc_zero_copy_send;
|
||||
@ -39,6 +40,8 @@ sysctl_t sysctls[] = {
|
||||
&ngx_freebsd_net_inet_tcp_sendspace,
|
||||
sizeof(int)},
|
||||
|
||||
/* FreeBSD 5.0 */
|
||||
|
||||
{"kern.ipc.zero_copy.send",
|
||||
&ngx_freebsd_kern_ipc_zero_copy_send,
|
||||
sizeof(int)},
|
||||
@ -49,7 +52,7 @@ sysctl_t sysctls[] = {
|
||||
|
||||
int ngx_os_init(ngx_log_t *log)
|
||||
{
|
||||
int i;
|
||||
int i, version;
|
||||
size_t size;
|
||||
ngx_err_t err;
|
||||
|
||||
@ -81,9 +84,11 @@ int ngx_os_init(ngx_log_t *log)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
version = ngx_freebsd_kern_osreldate;
|
||||
|
||||
ngx_log_error(NGX_LOG_INFO, log, 0,
|
||||
"kern.osreldate: %d, built on %d",
|
||||
ngx_freebsd_kern_osreldate, __FreeBSD_version);
|
||||
version, __FreeBSD_version);
|
||||
|
||||
|
||||
#if (HAVE_FREEBSD_SENDFILE)
|
||||
@ -91,12 +96,12 @@ int ngx_os_init(ngx_log_t *log)
|
||||
/* The determination of the sendfile() nbytes bug is complex enough.
|
||||
There're two sendfile() syscalls: a new 393 has no bug while
|
||||
an old 336 has the bug in some versions and has not in others.
|
||||
libc_r wrapper also emulates the bug in some versions.
|
||||
Besides libc_r wrapper also emulates the bug in some versions.
|
||||
There's no way to say exactly if a given FreeBSD version has bug.
|
||||
Here is the algorithm that work at least for RELEASEs
|
||||
Here is the algorithm that works at least for RELEASEs
|
||||
and for syscalls only (not libc_r wrapper). */
|
||||
|
||||
/* detect was the new sendfile() version available at the compile time
|
||||
/* detect the new sendfile() version available at the compile time
|
||||
to allow an old binary to run correctly on an updated FreeBSD system. */
|
||||
|
||||
#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \
|
||||
@ -115,6 +120,11 @@ int ngx_os_init(ngx_log_t *log)
|
||||
#endif /* HAVE_FREEBSD_SENDFILE */
|
||||
|
||||
|
||||
if ((version < 500000 && version >= 440003) || version >= 500017) {
|
||||
ngx_freebsd_tcp_nopush_flush = 1;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; sysctls[i].name; i++) {
|
||||
*sysctls[i].value = 0;
|
||||
size = sysctls[i].size;
|
||||
|
@ -20,6 +20,8 @@ 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;
|
||||
extern int ngx_freebsd_tcp_nopush_flush;
|
||||
extern int ngx_freebsd_kern_ipc_zero_copy_send;
|
||||
|
||||
|
||||
#endif /* _NGX_FREEBSD_INIT_H_INCLUDED_ */
|
||||
|
@ -13,9 +13,9 @@
|
||||
and the first part of the file in one packet but also sends 4K pages
|
||||
in the full packets.
|
||||
|
||||
The turning TCP_NOPUSH off flushes any pending data at least in FreeBSD 4.2,
|
||||
although there's special fix in src/sys/netinet/tcp_usrreq.c just before
|
||||
FreeBSD 4.5.
|
||||
Until FreeBSD 4.5 the turning TCP_NOPUSH off does not not flush
|
||||
the pending data that less than MSS and the data sent with 5 second delay.
|
||||
So we use TCP_NOPUSH on FreeBSD 4.5+ only.
|
||||
*/
|
||||
|
||||
|
||||
@ -105,14 +105,15 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
||||
|
||||
if (file) {
|
||||
|
||||
if (tcp_nopush == 0) {
|
||||
if (!c->tcp_nopush && ngx_freebsd_tcp_nopush_flush) {
|
||||
c->tcp_nopush = 1;
|
||||
tcp_nopush = 1;
|
||||
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
|
||||
(const void *) &tcp_nopush,
|
||||
sizeof(int)) == -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
|
||||
"setsockopt(TCP_NO_PUSH) failed");
|
||||
"setsockopt(TCP_NOPUSH) failed");
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
}
|
||||
@ -221,14 +222,18 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in)
|
||||
|
||||
} while ((tail && tail == ce) || eintr);
|
||||
|
||||
if (tcp_nopush == 1) {
|
||||
/* STUB: should be in app code, no need to clear TCP_NOPUSH
|
||||
if the conneciton close()d or shutdown()ed */
|
||||
|
||||
if (c->tcp_nopush) {
|
||||
c->tcp_nopush = 0;
|
||||
tcp_nopush = 0;
|
||||
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NOPUSH,
|
||||
(const void *) &tcp_nopush,
|
||||
sizeof(int)) == -1)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, c->log, ngx_errno,
|
||||
"setsockopt(!TCP_NO_PUSH) failed");
|
||||
"setsockopt(!TCP_NOPUSH) failed");
|
||||
return NGX_CHAIN_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,20 @@
|
||||
|
||||
|
||||
|
||||
#define ngx_open_file(name, flags) \
|
||||
#define ngx_open_file(name, access, create) \
|
||||
CreateFile(name, flags, \
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, \
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)
|
||||
NULL, create, FILE_FLAG_BACKUP_SEMANTICS, NULL)
|
||||
/*
|
||||
NULL, OPEN_EXISTING, 0, NULL)
|
||||
*/
|
||||
#define ngx_open_file_n "CreateFile()"
|
||||
|
||||
#define NGX_FILE_RDONLY GENERIC_READ
|
||||
#define NGX_FILE_RDWR GENERIC_READ|GENERIC_WRITE
|
||||
#define NGX_FILE_CREATE_OR_OPEN OPEN_ALWAYS
|
||||
#define NGX_FILE_OPEN OPEN_EXISTING
|
||||
|
||||
|
||||
#define ngx_open_tempfile(name, persistent) \
|
||||
CreateFile(name, \
|
||||
@ -40,10 +47,6 @@
|
||||
|
||||
|
||||
|
||||
#define ngx_open_file_n "CreateFile()"
|
||||
|
||||
#define NGX_FILE_RDONLY GENERIC_READ
|
||||
|
||||
#define ngx_close_file CloseHandle
|
||||
#define ngx_close_file_n "CloseHandle()"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user