mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 01:12:40 +08:00
nginx-0.0.1-2003-11-09-23:03:38 import; separate building
This commit is contained in:
parent
e8732b06b9
commit
74e95c224a
@ -168,7 +168,15 @@ ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data);
|
||||
|
||||
} else if (cmd->type & NGX_CONF_1MORE) {
|
||||
|
||||
if (cf->args->nelts != 1) {
|
||||
if (cf->args->nelts > 1) {
|
||||
valid = 1;
|
||||
} else {
|
||||
valid = 0;
|
||||
}
|
||||
|
||||
} else if (cmd->type & NGX_CONF_2MORE) {
|
||||
|
||||
if (cf->args->nelts > 2) {
|
||||
valid = 1;
|
||||
} else {
|
||||
valid = 0;
|
||||
|
@ -23,14 +23,19 @@
|
||||
#define NGX_CONF_TAKE8 0x00000100
|
||||
#define NGX_CONF_TAKE9 0x00000200
|
||||
|
||||
#define NGX_CONF_TAKE12 (NGX_CONF_TAKE1|NGX_CONF_TAKE2)
|
||||
|
||||
#define NGX_CONF_TAKE13 (NGX_CONF_TAKE1|NGX_CONF_TAKE3)
|
||||
|
||||
#define NGX_CONF_TAKE1234 (NGX_CONF_TAKE1|NGX_CONF_TAKE2|NGX_CONF_TAKE3 \
|
||||
|NGX_CONF_TAKE4)
|
||||
|
||||
#define NGX_CONF_ARGS_NUMBER 0x0000ffff
|
||||
#define NGX_CONF_ANY 0x00010000
|
||||
#define NGX_CONF_1MORE 0x00020000
|
||||
#define NGX_CONF_BLOCK 0x00040000
|
||||
#define NGX_CONF_FLAG 0x00080000
|
||||
#define NGX_CONF_BLOCK 0x00010000
|
||||
#define NGX_CONF_FLAG 0x00020000
|
||||
#define NGX_CONF_ANY 0x00040000
|
||||
#define NGX_CONF_1MORE 0x00080000
|
||||
#define NGX_CONF_2MORE 0x00100000
|
||||
|
||||
#define NGX_MAIN_CONF 0x01000000
|
||||
|
||||
|
@ -27,6 +27,7 @@ extern ngx_module_t ngx_aio_module;
|
||||
|
||||
extern ngx_module_t ngx_http_module;
|
||||
extern ngx_module_t ngx_http_core_module;
|
||||
extern ngx_module_t ngx_http_log_module;
|
||||
|
||||
extern ngx_module_t ngx_http_write_filter_module;
|
||||
extern ngx_module_t ngx_http_output_filter_module;
|
||||
@ -42,8 +43,6 @@ extern ngx_module_t ngx_http_static_module;
|
||||
extern ngx_module_t ngx_http_index_module;
|
||||
extern ngx_module_t ngx_http_proxy_module;
|
||||
|
||||
extern ngx_module_t ngx_http_log_module;
|
||||
|
||||
|
||||
ngx_module_t *ngx_modules[] = {
|
||||
|
||||
@ -78,6 +77,7 @@ ngx_module_t *ngx_modules[] = {
|
||||
&ngx_http_module,
|
||||
|
||||
&ngx_http_core_module,
|
||||
&ngx_http_log_module,
|
||||
&ngx_http_write_filter_module,
|
||||
&ngx_http_output_filter_module,
|
||||
&ngx_http_header_filter_module,
|
||||
@ -93,7 +93,5 @@ ngx_module_t *ngx_modules[] = {
|
||||
&ngx_http_index_module,
|
||||
&ngx_http_proxy_module,
|
||||
|
||||
&ngx_http_log_module,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
@ -71,13 +71,15 @@ int ngx_atoi(char *line, size_t n)
|
||||
|
||||
void ngx_md5_text(char *text, u_char *md5)
|
||||
{
|
||||
/* STUB */
|
||||
int i;
|
||||
static char hex[] = "0123456789abcdef";
|
||||
|
||||
ngx_snprintf(text, 33,
|
||||
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
||||
md5[0], md5[1], md5[2], md5[3], md5[4], md5[5],
|
||||
md5[6], md5[7], md5[8], md5[9], md5[10], md5[11],
|
||||
md5[12], md5[13], md5[14], md5[15]);
|
||||
for (i = 0; i < 16; i++) {
|
||||
*text++ = hex[md5[i] >> 4];
|
||||
*text++ = hex[md5[i] & 0xf];
|
||||
}
|
||||
|
||||
*text = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
@ -417,6 +417,7 @@ int ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
|
||||
}
|
||||
|
||||
/* TODO: free hunk if p->free_bufs && upstream done */
|
||||
|
||||
/* add the free shadow raw hunk to p->free_raw_hunks */
|
||||
|
||||
if (cl->hunk->type & NGX_HUNK_LAST_SHADOW) {
|
||||
|
@ -1,202 +0,0 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_open_file_t *file;
|
||||
} ngx_http_log_conf_t;
|
||||
|
||||
|
||||
static void *ngx_http_log_create_conf(ngx_conf_t *cf);
|
||||
static char *ngx_http_log_merge_conf(ngx_conf_t *cf, 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 */
|
||||
NULL /* init child */
|
||||
};
|
||||
|
||||
|
||||
static ngx_str_t http_access_log = ngx_string("access.log");
|
||||
|
||||
|
||||
static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
|
||||
int ngx_http_log_handler(ngx_http_request_t *r)
|
||||
{
|
||||
char *line, *p;
|
||||
size_t len;
|
||||
ngx_tm_t tm;
|
||||
ngx_http_log_conf_t *lcf;
|
||||
#if (WIN32)
|
||||
int written;
|
||||
#endif
|
||||
|
||||
ngx_log_debug(r->connection->log, "log handler");
|
||||
|
||||
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 + 2 + 7 + 2;
|
||||
#else
|
||||
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;
|
||||
|
||||
ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
|
||||
p += r->connection->addr_text.len;
|
||||
|
||||
*p++ = ' ';
|
||||
|
||||
p += ngx_snprintf(p, 21, "%u", r->connection->number);
|
||||
|
||||
*p++ = ' ';
|
||||
|
||||
if (r->pipeline) {
|
||||
*p++ = 'p';
|
||||
} else {
|
||||
*p++ = '.';
|
||||
}
|
||||
|
||||
*p++ = ' ';
|
||||
|
||||
ngx_localtime(&tm);
|
||||
|
||||
*p++ = '[';
|
||||
p += ngx_snprintf(p, 21, "%02d/%s/%d:%02d:%02d:%02d",
|
||||
tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1],
|
||||
tm.ngx_tm_year,
|
||||
tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
|
||||
|
||||
*p++ = ']';
|
||||
|
||||
*p++ = ' ';
|
||||
|
||||
*p++ = '"';
|
||||
ngx_memcpy(p, r->request_line.data, r->request_line.len);
|
||||
p += r->request_line.len;
|
||||
*p++ = '"';
|
||||
|
||||
*p++ = ' ';
|
||||
|
||||
p += ngx_snprintf(p, 4, "%d", r->headers_out.status);
|
||||
|
||||
*p++ = ' ';
|
||||
|
||||
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;
|
||||
WriteFile(lcf->file->fd, line, p - line, &written, NULL);
|
||||
|
||||
#else
|
||||
|
||||
*p++ = LF;
|
||||
write(lcf->file->fd, line, p - line);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void *ngx_http_log_create_conf(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_http_log_conf_t *conf;
|
||||
|
||||
ngx_test_null(conf, ngx_pcalloc(cf->pool, sizeof(ngx_http_log_conf_t)),
|
||||
NGX_CONF_ERROR);
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
{
|
||||
ngx_http_log_conf_t *prev = parent;
|
||||
ngx_http_log_conf_t *conf = child;
|
||||
|
||||
if (conf->file == NULL) {
|
||||
if (prev->file) {
|
||||
conf->file = prev->file;
|
||||
} else {
|
||||
ngx_test_null(conf->file,
|
||||
ngx_conf_open_file(cf->cycle, &http_access_log),
|
||||
NGX_CONF_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ngx_str_t *value;
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
ngx_test_null(lcf->file, ngx_conf_open_file(cf->cycle, &value[1]),
|
||||
NGX_CONF_ERROR);
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
#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_ */
|
@ -158,22 +158,6 @@ ngx_log_debug(r->connection->log, "FILE: %d" _ r->file.fd);
|
||||
r->file.info_valid = 1;
|
||||
}
|
||||
|
||||
#if !(WIN32) /* the not regular files are probably Unix specific */
|
||||
|
||||
if (!ngx_is_file(r->file.info)) {
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
|
||||
"%s is not a regular file", r->file.name.data);
|
||||
|
||||
if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (ngx_is_dir(r->file.info)) {
|
||||
ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
|
||||
|
||||
@ -203,6 +187,22 @@ ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->file.name.data);
|
||||
return NGX_HTTP_MOVED_PERMANENTLY;
|
||||
}
|
||||
|
||||
#if !(WIN32) /* the not regular files are probably Unix specific */
|
||||
|
||||
if (!ngx_is_file(r->file.info)) {
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
|
||||
"%s is not a regular file", r->file.name.data);
|
||||
|
||||
if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR)
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
r->content_handler = ngx_http_static_handler;
|
||||
|
||||
return NGX_OK;
|
||||
|
@ -5,12 +5,14 @@
|
||||
#include <ngx_http_proxy_handler.h>
|
||||
|
||||
|
||||
static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p,
|
||||
int rc);
|
||||
static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p);
|
||||
static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p);
|
||||
|
||||
|
||||
int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
int rc;
|
||||
char *last;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_proxy_cache_t *c;
|
||||
@ -54,44 +56,69 @@ int ngx_http_proxy_get_cached_response(ngx_http_proxy_ctx_t *p)
|
||||
|
||||
c->ctx.buf = p->header_in;
|
||||
|
||||
rc = ngx_http_cache_get_file(r, &c->ctx);
|
||||
return ngx_http_proxy_process_cached_response(p,
|
||||
ngx_http_cache_get_file(r, &c->ctx));
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
case NGX_HTTP_CACHE_STALE:
|
||||
p->stale = 1;
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_EXPR;
|
||||
break;
|
||||
|
||||
case NGX_HTTP_CACHE_AGED:
|
||||
p->stale = 1;
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_AGED;
|
||||
break;
|
||||
static int ngx_http_proxy_process_cached_response(ngx_http_proxy_ctx_t *p,
|
||||
int rc)
|
||||
{
|
||||
if (rc == NGX_OK) {
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_HIT;
|
||||
p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
|
||||
|
||||
case NGX_OK:
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_HIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_MISS;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK
|
||||
|| rc == NGX_HTTP_CACHE_STALE
|
||||
|| rc == NGX_HTTP_CACHE_AGED)
|
||||
{
|
||||
p->header_in->pos = p->header_in->start + c->ctx.header_size;
|
||||
if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
p->header_in->pos = p->header_in->start + c->ctx.header_size;
|
||||
|
||||
p->valid_header_in = 1;
|
||||
|
||||
return ngx_http_proxy_send_cached_response(p);
|
||||
}
|
||||
|
||||
if (rc == NGX_HTTP_CACHE_STALE) {
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_EXPR;
|
||||
|
||||
} else if (rc == NGX_HTTP_CACHE_AGED) {
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_AGED;
|
||||
}
|
||||
|
||||
if (rc == NGX_HTTP_CACHE_STALE || rc == NGX_HTTP_CACHE_AGED) {
|
||||
p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
|
||||
|
||||
if (ngx_http_proxy_process_cached_header(p) == NGX_ERROR) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
|
||||
p->header_in->last = p->header_in->pos;
|
||||
|
||||
p->stale = 1;
|
||||
p->valid_header_in = 1;
|
||||
|
||||
} else if (rc == NGX_DECLINED) {
|
||||
p->header_in->pos = p->header_in->start + c->ctx.header_size;
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_MISS;
|
||||
p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
|
||||
p->header_in->last = p->header_in->pos;
|
||||
}
|
||||
|
||||
return rc;
|
||||
if (p->lcf->busy_lock) {
|
||||
p->try_busy_lock = 1;
|
||||
|
||||
p->header_in->pos = p->header_in->start;
|
||||
p->header_in->last = p->header_in->start;
|
||||
|
||||
p->busy_lock.time = 0;
|
||||
p->busy_lock.event = p->request->connection->read;
|
||||
p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler;
|
||||
p->busy_lock.md5 = p->cache->ctx.md5;
|
||||
|
||||
ngx_http_proxy_cache_busy_lock(p);
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
return ngx_http_proxy_request_upstream(p);
|
||||
}
|
||||
|
||||
|
||||
@ -141,6 +168,7 @@ static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p)
|
||||
ngx_log_debug(r->connection->log, "http cache status %d '%s'" _
|
||||
c->status _ c->status_line.data);
|
||||
|
||||
/* TODO: ngx_init_table */
|
||||
c->headers_in.headers = ngx_create_table(r->pool, 20);
|
||||
|
||||
for ( ;; ) {
|
||||
@ -216,28 +244,109 @@ static int ngx_http_proxy_process_cached_header(ngx_http_proxy_ctx_t *p)
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p)
|
||||
void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
rc = ngx_http_busy_lock(p->lcf->busy_lock, p->cache->ctx.md5);
|
||||
int rc, ft_type;
|
||||
|
||||
rc = ngx_http_busy_lock_cachable(p->lcf->busy_lock, &p->busy_lock,
|
||||
p->try_busy_lock);
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
ngx_http_proxy_request_upstream(p);
|
||||
if (p->try_busy_lock) {
|
||||
p->busy_locked = 1;
|
||||
p->header_in->pos = p->header_in->start + p->cache->ctx.header_size;
|
||||
p->header_in->last = p->header_in->pos;
|
||||
|
||||
ngx_http_proxy_request_upstream(p);
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_proxy_cache_look_complete_request(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
if (p->busy_lock_time) {
|
||||
ngx_add_timer(p->request->connection->read, 1000);
|
||||
p->try_busy_lock = 0;
|
||||
|
||||
if (p->cache->ctx.file.fd != NGX_INVALID_FILE
|
||||
&& !p->cache->ctx.file.info_valid)
|
||||
{
|
||||
if (ngx_stat_fd(p->cache->ctx.file.fd, &p->cache->ctx.file.info)
|
||||
== NGX_FILE_ERROR)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, p->request->connection->log, ngx_errno,
|
||||
ngx_stat_fd_n " \"%s\" failed",
|
||||
p->cache->ctx.file.name.data);
|
||||
ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
p->cache->ctx.file.info_valid = 1;
|
||||
}
|
||||
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == NGX_DONE) {
|
||||
ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
|
||||
|
||||
} else {
|
||||
/* rc == NGX_ERROR */
|
||||
ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
|
||||
}
|
||||
|
||||
if (p->stale && (p->lcf->use_stale & ft_type)) {
|
||||
ngx_http_proxy_finalize_request(p,
|
||||
ngx_http_proxy_send_cached_response(p));
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
|
||||
static void ngx_http_proxy_cache_look_complete_request(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
int rc;
|
||||
ngx_http_cache_ctx_t *ctx;
|
||||
|
||||
if (!(ctx = ngx_pcalloc(p->request->pool, sizeof(ngx_http_cache_ctx_t)))) {
|
||||
ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
*ctx = p->cache->ctx;
|
||||
|
||||
rc = ngx_http_cache_open_file(p->request, ctx,
|
||||
ngx_file_uniq(p->cache->ctx.file.info));
|
||||
|
||||
if (rc == NGX_HTTP_CACHE_THE_SAME) {
|
||||
p->try_busy_lock = 1;
|
||||
p->busy_lock.time = 0;
|
||||
ngx_http_proxy_cache_busy_lock(p);
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_log_debug(p->request->connection->log, "OLD: %d, NEW: %d" _
|
||||
p->cache->ctx.file.fd _ ctx->file.fd);
|
||||
|
||||
if (p->cache->ctx.file.fd != NGX_INVALID_FILE) {
|
||||
if (ngx_close_file(p->cache->ctx.file.fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, p->request->connection->log, ngx_errno,
|
||||
ngx_close_file_n " \"%s\" failed",
|
||||
p->cache->ctx.file.name.data);
|
||||
}
|
||||
}
|
||||
|
||||
rc == NGX_ERROR
|
||||
check waitn
|
||||
}
|
||||
p->cache->ctx = *ctx;
|
||||
|
||||
#endif
|
||||
p->status = 0;
|
||||
p->status_count = 0;
|
||||
|
||||
ngx_http_proxy_finalize_request(p,
|
||||
ngx_http_proxy_process_cached_response(p, rc));
|
||||
}
|
||||
|
||||
|
||||
int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p)
|
||||
@ -435,8 +544,8 @@ int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p)
|
||||
/* FIXME: time_t == int_64_t, we can use fpu */
|
||||
|
||||
p->state->reason = NGX_HTTP_PROXY_CACHE_LMF;
|
||||
p->cache->ctx.expires = ngx_time()
|
||||
+ (((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100;
|
||||
p->cache->ctx.expires = (time_t) (ngx_time()
|
||||
+ (((int64_t) (date - last_modified)) * p->lcf->lm_factor) / 100);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -460,6 +569,9 @@ int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p)
|
||||
|
||||
ep = p->upstream->event_pipe;
|
||||
|
||||
ngx_log_debug(p->request->connection->log, "LEN: " OFF_FMT ", " OFF_FMT _
|
||||
p->cache->ctx.length _ ep->read_length);
|
||||
|
||||
if (p->cache->ctx.length == -1) {
|
||||
/* TODO: test rc */
|
||||
ngx_write_file(&ep->temp_file->file,
|
||||
|
@ -132,7 +132,7 @@ static ngx_command_t ngx_http_proxy_commands[] = {
|
||||
|
||||
|
||||
{ ngx_string("proxy_busy_lock"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13,
|
||||
ngx_http_set_busy_lock_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, busy_lock),
|
||||
@ -240,9 +240,31 @@ ngx_http_header_t ngx_http_proxy_headers_in[] = {
|
||||
};
|
||||
|
||||
|
||||
static ngx_str_t cache_states[] = {
|
||||
ngx_string("PASS"),
|
||||
ngx_string("BYPASS"),
|
||||
ngx_string("AUTH"),
|
||||
ngx_string("PGNC"),
|
||||
ngx_string("MISS"),
|
||||
ngx_string("EXPR"),
|
||||
ngx_string("AGED"),
|
||||
ngx_string("HIT")
|
||||
};
|
||||
|
||||
|
||||
static ngx_str_t cache_reason[] = {
|
||||
ngx_string("BPS"),
|
||||
ngx_string("XAE"),
|
||||
ngx_string("CTL"),
|
||||
ngx_string("EXP"),
|
||||
ngx_string("MVD"),
|
||||
ngx_string("LMF"),
|
||||
ngx_string("PDE")
|
||||
};
|
||||
|
||||
|
||||
static int ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
{
|
||||
int rc;
|
||||
ngx_http_proxy_ctx_t *p;
|
||||
|
||||
ngx_http_create_ctx(r, p, ngx_http_proxy_module,
|
||||
@ -269,16 +291,16 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
if (!p->lcf->cache
|
||||
|| (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD))
|
||||
{
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_PASS;
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_PASS;
|
||||
|
||||
} else if (r->bypass_cache) {
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_BYPASS;
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_BYPASS;
|
||||
|
||||
} else if (r->headers_in.authorization) {
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_AUTH;
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_AUTH;
|
||||
|
||||
} else if (r->no_cache) {
|
||||
p->state->cache = NGX_HTTP_PROXY_CACHE_PGNC;
|
||||
p->state->cache_state = NGX_HTTP_PROXY_CACHE_PGNC;
|
||||
p->cachable = 1;
|
||||
|
||||
} else {
|
||||
@ -286,25 +308,72 @@ static int ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
}
|
||||
|
||||
|
||||
if (p->state->cache) {
|
||||
if (p->state->cache_state != 0) {
|
||||
return ngx_http_proxy_request_upstream(p);
|
||||
}
|
||||
|
||||
rc = ngx_http_proxy_get_cached_response(p);
|
||||
return ngx_http_proxy_get_cached_response(p);
|
||||
}
|
||||
|
||||
if (rc == NGX_DONE || rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
|
||||
return rc;
|
||||
|
||||
void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_proxy_ctx_t *p;
|
||||
|
||||
ngx_log_debug(rev->log, "busy lock");
|
||||
|
||||
c = rev->data;
|
||||
r = c->data;
|
||||
p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
||||
p->action = "waiting upstream in busy lock";
|
||||
|
||||
if (rev->timedout) {
|
||||
rev->timedout = 0;
|
||||
p->busy_lock.time++;
|
||||
p->state->bl_time = p->busy_lock.time;
|
||||
if (p->state->cache_state < NGX_HTTP_PROXY_CACHE_MISS) {
|
||||
ngx_http_proxy_upstream_busy_lock(p);
|
||||
|
||||
} else {
|
||||
ngx_http_proxy_cache_busy_lock(p);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
p->valid_header_in = 1;
|
||||
ngx_log_debug(rev->log, "client sent while busy lock");
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
return ngx_http_proxy_send_cached_response(p);
|
||||
/*
|
||||
* TODO: kevent() notify about error, otherwise we need to
|
||||
* call ngx_peek(): recv(MGS_PEEK) to get errno. THINK about aio
|
||||
* if there's no error we need to disable event.
|
||||
*/
|
||||
|
||||
#if (HAVE_KQUEUE)
|
||||
|
||||
if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) {
|
||||
p->lcf->busy_lock->waiting--;
|
||||
|
||||
ngx_del_timer(rev);
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno,
|
||||
"client() closed connection");
|
||||
|
||||
if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) {
|
||||
ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* we have not HTTP code for the case when a client cancels a request */
|
||||
|
||||
ngx_http_proxy_finalize_request(p, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* rc == NGX_DECLINED || NGX_HTTP_CACHE_STALE || NGX_HTTP_CACHE_AGED */
|
||||
#endif
|
||||
|
||||
return ngx_http_proxy_request_upstream(p);
|
||||
}
|
||||
|
||||
|
||||
@ -313,7 +382,7 @@ void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
|
||||
ngx_log_debug(p->request->connection->log,
|
||||
"finalize http proxy request");
|
||||
|
||||
if (p->upstream->peer.connection) {
|
||||
if (p->upstream && p->upstream->peer.connection) {
|
||||
ngx_http_proxy_close_connection(p);
|
||||
}
|
||||
|
||||
@ -323,8 +392,10 @@ void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
p->request->connection->log->data = p->saved_ctx;
|
||||
p->request->connection->log->handler = p->saved_handler;
|
||||
if (p->saved_ctx) {
|
||||
p->request->connection->log->data = p->saved_ctx;
|
||||
p->request->connection->log->handler = p->saved_handler;
|
||||
}
|
||||
|
||||
ngx_http_finalize_request(p->request, rc);
|
||||
}
|
||||
@ -338,7 +409,7 @@ void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p)
|
||||
p->upstream->peer.connection = NULL;
|
||||
|
||||
if (p->lcf->busy_lock) {
|
||||
p->lcf->busy_lock->conn_n--;
|
||||
p->lcf->busy_lock->busy--;
|
||||
}
|
||||
|
||||
ngx_log_debug(c->log, "proxy close connection: %d" _ c->fd);
|
||||
@ -382,6 +453,12 @@ void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p)
|
||||
}
|
||||
|
||||
|
||||
size_t ngx_http_proxy_log_state(void *data, char *buf, size_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len)
|
||||
{
|
||||
ngx_http_proxy_ctx_t *p = data;
|
||||
@ -513,21 +590,21 @@ static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
|
||||
conf->busy_lock = prev->busy_lock;
|
||||
}
|
||||
|
||||
if (conf->busy_lock && conf->cache && conf->busy_lock->busy == NULL) {
|
||||
if (conf->busy_lock && conf->cache && conf->busy_lock->md5 == NULL) {
|
||||
|
||||
/* ngx_alloc_shared() */
|
||||
conf->busy_lock->busy_mask =
|
||||
ngx_palloc(cf->pool, (conf->busy_lock->max_conn + 7) / 8);
|
||||
if (conf->busy_lock->busy_mask == NULL) {
|
||||
/* ngx_calloc_shared() */
|
||||
conf->busy_lock->md5_mask =
|
||||
ngx_pcalloc(cf->pool, (conf->busy_lock->max_busy + 7) / 8);
|
||||
if (conf->busy_lock->md5_mask == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
/* 16 bytes are 128 bits of the md5 */
|
||||
|
||||
/* ngx_alloc_shared() */
|
||||
conf->busy_lock->busy = ngx_palloc(cf->pool,
|
||||
16 * conf->busy_lock->max_conn);
|
||||
if (conf->busy_lock->busy == NULL) {
|
||||
conf->busy_lock->md5 = ngx_palloc(cf->pool,
|
||||
16 * conf->busy_lock->max_busy);
|
||||
if (conf->busy_lock->md5 == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -80,10 +80,24 @@ typedef struct {
|
||||
} ngx_http_proxy_loc_conf_t;
|
||||
|
||||
|
||||
/*
|
||||
* "EXPR/10/5/- 200/EXP/60 4"
|
||||
* "MISS/-/-/B 503/-/- -"
|
||||
* "EXPR/10/20/SB HIT/-/- -"
|
||||
* "EXPR/10/15/NB HIT/-/- -"
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
ngx_http_proxy_state_e cache;
|
||||
ngx_http_proxy_reason_e reason;
|
||||
ngx_http_proxy_state_e cache_state;
|
||||
time_t expired;
|
||||
time_t bl_time;
|
||||
int bl_state;
|
||||
|
||||
int status;
|
||||
ngx_http_proxy_reason_e reason;
|
||||
time_t time;
|
||||
time_t expires;
|
||||
|
||||
ngx_str_t *peer;
|
||||
} ngx_http_proxy_state_t;
|
||||
|
||||
@ -140,12 +154,14 @@ struct ngx_http_proxy_ctx_s {
|
||||
|
||||
ngx_hunk_t *header_in;
|
||||
|
||||
time_t busy_lock_time;
|
||||
ngx_http_busy_lock_ctx_t busy_lock;
|
||||
|
||||
unsigned accel:1;
|
||||
|
||||
unsigned cachable:1;
|
||||
unsigned stale:1;
|
||||
unsigned try_busy_lock:1;
|
||||
unsigned busy_locked:1;
|
||||
unsigned valid_header_in:1;
|
||||
|
||||
unsigned request_sent:1;
|
||||
@ -187,6 +203,10 @@ int ngx_http_proxy_send_cached_response(ngx_http_proxy_ctx_t *p);
|
||||
int ngx_http_proxy_is_cachable(ngx_http_proxy_ctx_t *p);
|
||||
int ngx_http_proxy_update_cache(ngx_http_proxy_ctx_t *p);
|
||||
|
||||
void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev);
|
||||
void ngx_http_proxy_cache_busy_lock(ngx_http_proxy_ctx_t *p);
|
||||
void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
|
||||
|
||||
size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len);
|
||||
void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
|
||||
void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p);
|
||||
|
@ -11,8 +11,6 @@
|
||||
static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p);
|
||||
static void ngx_http_proxy_init_upstream(void *data);
|
||||
static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p);
|
||||
static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
|
||||
static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev);
|
||||
static void ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p);
|
||||
static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
|
||||
static void ngx_http_proxy_send_request_handler(ngx_event_t *wev);
|
||||
@ -266,7 +264,7 @@ ngx_log_debug(r->connection->log, "timer_set: %d" _
|
||||
|
||||
wctx->pool = r->pool;
|
||||
|
||||
if (p->lcf->busy_lock) {
|
||||
if (p->lcf->busy_lock && !p->busy_locked) {
|
||||
ngx_http_proxy_upstream_busy_lock(p);
|
||||
} else {
|
||||
ngx_http_proxy_connect(p);
|
||||
@ -312,41 +310,31 @@ static void ngx_http_proxy_reinit_upstream(ngx_http_proxy_ctx_t *p)
|
||||
}
|
||||
|
||||
|
||||
static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
|
||||
void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
|
||||
{
|
||||
int ft_type;
|
||||
int rc, ft_type;
|
||||
|
||||
if (p->lcf->busy_lock->conn_n < p->lcf->busy_lock->max_conn) {
|
||||
p->lcf->busy_lock->conn_n++;
|
||||
if (p->busy_lock.time == 0) {
|
||||
p->busy_lock.event = p->request->connection->read;
|
||||
p->busy_lock.event_handler = ngx_http_proxy_busy_lock_handler;
|
||||
}
|
||||
|
||||
if (p->busy_lock_time) {
|
||||
p->busy_lock_time = 0;
|
||||
p->lcf->busy_lock->waiting_n--;
|
||||
}
|
||||
rc = ngx_http_busy_lock(p->lcf->busy_lock, &p->busy_lock);
|
||||
|
||||
if (rc == NGX_AGAIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
ngx_http_proxy_connect(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p->busy_lock_time) {
|
||||
if (p->busy_lock_time < p->lcf->busy_lock->timeout) {
|
||||
ngx_add_timer(p->request->connection->read, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
p->lcf->busy_lock->waiting_n--;
|
||||
if (rc == NGX_DONE) {
|
||||
ft_type = NGX_HTTP_PROXY_FT_BUSY_LOCK;
|
||||
|
||||
} else {
|
||||
if (p->lcf->busy_lock->waiting_n < p->lcf->busy_lock->max_waiting) {
|
||||
p->lcf->busy_lock->waiting_n++;
|
||||
ngx_add_timer(p->request->connection->read, 1000);
|
||||
p->request->connection->read->event_handler =
|
||||
ngx_http_proxy_upstream_busy_lock_handler;
|
||||
/* TODO: ngx_handle_level_read_event() */
|
||||
return;
|
||||
}
|
||||
|
||||
/* rc == NGX_ERROR */
|
||||
ft_type = NGX_HTTP_PROXY_FT_MAX_WAITING;
|
||||
}
|
||||
|
||||
@ -357,61 +345,6 @@ static void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p)
|
||||
}
|
||||
|
||||
ngx_http_proxy_finalize_request(p, NGX_HTTP_SERVICE_UNAVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void ngx_http_proxy_upstream_busy_lock_handler(ngx_event_t *rev)
|
||||
{
|
||||
ngx_connection_t *c;
|
||||
ngx_http_request_t *r;
|
||||
ngx_http_proxy_ctx_t *p;
|
||||
|
||||
ngx_log_debug(rev->log, "busy lock");
|
||||
|
||||
c = rev->data;
|
||||
r = c->data;
|
||||
p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
||||
p->action = "waiting upstream in busy lock";
|
||||
|
||||
if (rev->timedout) {
|
||||
rev->timedout = 0;
|
||||
p->busy_lock_time++;
|
||||
ngx_http_proxy_upstream_busy_lock(p);
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_log_debug(rev->log, "client sent while busy lock");
|
||||
|
||||
/*
|
||||
* TODO: kevent() notify about error, otherwise we need to
|
||||
* call ngx_peek(): recv(MGS_PEEK) to get errno. THINK about aio
|
||||
* if there's no error we need to disable event.
|
||||
*/
|
||||
|
||||
#if (HAVE_KQUEUE)
|
||||
|
||||
if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) {
|
||||
p->lcf->busy_lock->waiting_n--;
|
||||
|
||||
ngx_del_timer(rev);
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno,
|
||||
"client() closed connection");
|
||||
|
||||
if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) {
|
||||
ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* we have not HTTP code for the case when a client cancels a request */
|
||||
|
||||
ngx_http_proxy_finalize_request(p, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -724,6 +657,16 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
|
||||
}
|
||||
}
|
||||
|
||||
if (p->status == NGX_HTTP_NOT_FOUND
|
||||
&& p->upstream->peer.tries > 1
|
||||
&& p->lcf->next_upstream & NGX_HTTP_PROXY_FT_HTTP_404)
|
||||
{
|
||||
ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_HTTP_404);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: "proxy_error_page" */
|
||||
|
||||
p->upstream->status_line.len = p->status_end - p->status_start;
|
||||
p->upstream->status_line.data = ngx_palloc(p->request->pool,
|
||||
p->upstream->status_line.len + 1);
|
||||
@ -740,6 +683,7 @@ static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
|
||||
if (p->upstream->headers_in.headers) {
|
||||
p->upstream->headers_in.headers->nelts = 0;
|
||||
} else {
|
||||
/* TODO: ngx_init_table */
|
||||
p->upstream->headers_in.headers = ngx_create_table(p->request->pool,
|
||||
20);
|
||||
}
|
||||
@ -956,8 +900,8 @@ static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p)
|
||||
header->expires = p->cache->ctx.expires;
|
||||
header->last_modified = p->cache->ctx.last_modified;
|
||||
header->date = p->cache->ctx.date;
|
||||
/* TODO: r->headers_out.content_length_n == -1 */
|
||||
header->length = r->headers_out.content_length_n;
|
||||
p->cache->ctx.length = r->headers_out.content_length_n;
|
||||
|
||||
header->key_len = p->cache->ctx.key.len;
|
||||
ngx_memcpy(&header->key, p->cache->ctx.key.data, header->key_len);
|
||||
@ -1105,18 +1049,24 @@ static void ngx_http_proxy_process_body(ngx_event_t *ev)
|
||||
if (p->upstream->peer.connection) {
|
||||
if (ep->upstream_done && p->cachable) {
|
||||
if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
|
||||
ngx_http_busy_unlock_cachable(p->lcf->busy_lock, &p->busy_lock);
|
||||
ngx_http_proxy_finalize_request(p, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_busy_unlock_cachable(p->lcf->busy_lock, &p->busy_lock);
|
||||
|
||||
} else if (ep->upstream_eof && p->cachable) {
|
||||
|
||||
/* TODO: check length & update cache */
|
||||
|
||||
if (ngx_http_proxy_update_cache(p) == NGX_ERROR) {
|
||||
ngx_http_busy_unlock_cachable(p->lcf->busy_lock, &p->busy_lock);
|
||||
ngx_http_proxy_finalize_request(p, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
ngx_http_busy_unlock_cachable(p->lcf->busy_lock, &p->busy_lock);
|
||||
}
|
||||
|
||||
if (ep->upstream_done || ep->upstream_eof || ep->upstream_error) {
|
||||
@ -1206,7 +1156,7 @@ ngx_log_debug(p->request->connection->log, "next upstream: %d" _ ft_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (p->lcf->busy_lock) {
|
||||
if (p->lcf->busy_lock && !p->busy_locked) {
|
||||
ngx_http_proxy_upstream_busy_lock(p);
|
||||
} else {
|
||||
ngx_http_proxy_connect(p);
|
||||
|
@ -123,7 +123,6 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* parse inside the http{} block */
|
||||
|
||||
pcf = *cf;
|
||||
@ -131,14 +130,16 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
cf->module_type = NGX_HTTP_MODULE;
|
||||
cf->cmd_type = NGX_HTTP_MAIN_CONF;
|
||||
rv = ngx_conf_parse(cf, NULL);
|
||||
*cf = pcf;
|
||||
|
||||
if (rv != NGX_CONF_OK)
|
||||
if (rv != NGX_CONF_OK) {
|
||||
*cf = pcf;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/* init http{} main_conf's, merge the server{}s' srv_conf's
|
||||
and its location{}s' loc_conf's */
|
||||
/*
|
||||
* init http{} main_conf's, merge the server{}s' srv_conf's
|
||||
* and its location{}s' loc_conf's
|
||||
*/
|
||||
|
||||
cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
|
||||
cscfp = cmcf->servers.elts;
|
||||
@ -556,5 +557,6 @@ ngx_log_debug(cf->log, "%s %08x" _ s_name[n].name.data _
|
||||
}
|
||||
/**/
|
||||
|
||||
*cf = pcf;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <ngx_http_cache.h>
|
||||
#include <ngx_http_busy_lock.h>
|
||||
#include <ngx_http_filter.h>
|
||||
#include <ngx_http_log_handler.h>
|
||||
#include <ngx_http_core_module.h>
|
||||
|
||||
|
||||
|
@ -4,42 +4,151 @@
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5)
|
||||
|
||||
static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
|
||||
ngx_http_busy_lock_ctx_t *bc,
|
||||
int lock);
|
||||
|
||||
|
||||
int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
|
||||
{
|
||||
int i, b, busy, free;
|
||||
if (bl->busy < bl->max_busy) {
|
||||
bl->busy++;
|
||||
|
||||
if (bc->time) {
|
||||
bc->time = 0;
|
||||
bl->waiting--;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (bc->time) {
|
||||
if (bc->time < bl->timeout) {
|
||||
ngx_add_timer(bc->event, 1000);
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
bl->waiting--;
|
||||
return NGX_DONE;
|
||||
|
||||
}
|
||||
|
||||
if (bl->timeout == 0) {
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
if (bl->waiting < bl->max_waiting) {
|
||||
bl->waiting++;
|
||||
ngx_add_timer(bc->event, 1000);
|
||||
bc->event->event_handler = bc->event_handler;
|
||||
|
||||
/* TODO: ngx_handle_level_read_event() */
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
|
||||
ngx_http_busy_lock_ctx_t *bc, int lock)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ngx_http_busy_lock_look_cachable(bl, bc, lock);
|
||||
|
||||
ngx_log_debug(bc->event->log, "BUSYLOCK: %d" _ rc);
|
||||
|
||||
if (rc == NGX_OK) { /* no the same request, there's free slot */
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR && !lock) { /* no the same request, no free slot */
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
/* rc == NGX_AGAIN: the same request */
|
||||
|
||||
if (bc->time) {
|
||||
if (bc->time < bl->timeout) {
|
||||
ngx_add_timer(bc->event, 1000);
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
bl->waiting--;
|
||||
return NGX_DONE;
|
||||
|
||||
}
|
||||
|
||||
if (bl->timeout == 0) {
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
if (bl->waiting < bl->max_waiting) {
|
||||
bl->waiting++;
|
||||
ngx_add_timer(bc->event, 1000);
|
||||
bc->event->event_handler = bc->event_handler;
|
||||
|
||||
/* TODO: ngx_handle_level_read_event() */
|
||||
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void ngx_http_busy_unlock_cachable(ngx_http_busy_lock_t *bl,
|
||||
ngx_http_busy_lock_ctx_t *bc)
|
||||
{
|
||||
bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
|
||||
bl->cachable--;
|
||||
bl->busy--;
|
||||
}
|
||||
|
||||
|
||||
static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
|
||||
ngx_http_busy_lock_ctx_t *bc,
|
||||
int lock)
|
||||
{
|
||||
int i, b, cachable, free;
|
||||
u_int mask;
|
||||
|
||||
b = 0;
|
||||
busy = 0;
|
||||
cachable = 0;
|
||||
free = -1;
|
||||
|
||||
#if (NGX_SUPPRESS_WARN)
|
||||
mask = 0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < bl->max_conn; i++) {
|
||||
for (i = 0; i < bl->max_busy; i++) {
|
||||
|
||||
if ((b & 7) == 0) {
|
||||
mask = bl->busy_mask[i / 8];
|
||||
mask = bl->md5_mask[i / 8];
|
||||
}
|
||||
|
||||
if (mask & 1) {
|
||||
if (ngx_memcmp(&bl->busy[i * 16], md5, 16) == 0) {
|
||||
if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
busy++;
|
||||
cachable++;
|
||||
|
||||
} else if (free == -1) {
|
||||
free = i;
|
||||
}
|
||||
|
||||
if (busy == bl->busy_n) {
|
||||
if (busy < bl->max_conn) {
|
||||
#if 1
|
||||
if (cachable == bl->cachable) {
|
||||
if (free == -1 && cachable < bl->max_busy) {
|
||||
free = i + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
mask >>= 1;
|
||||
b++;
|
||||
@ -49,11 +158,18 @@ int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5)
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(&bl->busy[free * 16], md5, 16);
|
||||
bl->busy_mask[free / 8] |= free % 8;
|
||||
if (lock) {
|
||||
if (bl->busy == bl->max_busy) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
bl->busy_n++;
|
||||
bl->conn_n++;
|
||||
ngx_memcpy(&bl->md5[free * 16], bc->md5, 16);
|
||||
bl->md5_mask[free / 8] |= 1 << (free & 7);
|
||||
bc->slot = free;
|
||||
|
||||
bl->cachable++;
|
||||
bl->busy++;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
@ -64,8 +180,8 @@ char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
{
|
||||
char *p = conf;
|
||||
|
||||
int i;
|
||||
ngx_str_t *value;
|
||||
int i, dup, invalid;
|
||||
ngx_str_t *value, line;
|
||||
ngx_http_busy_lock_t *bl, **blp;
|
||||
|
||||
blp = (ngx_http_busy_lock_t **) (p + cmd->offset);
|
||||
@ -79,57 +195,86 @@ char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
}
|
||||
*blp = bl;
|
||||
|
||||
dup = 0;
|
||||
invalid = 0;
|
||||
value = (ngx_str_t *) cf->args->elts;
|
||||
|
||||
for (i = 1; i < 4; i++) {
|
||||
for (i = 1; i < cf->args->nelts; i++) {
|
||||
|
||||
if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "c:", 2) == 0) {
|
||||
if (bl->max_conn) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"duplicate \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
if (value[i].data[1] != '=') {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
switch (value[i].data[0]) {
|
||||
|
||||
case 'b':
|
||||
if (bl->max_busy) {
|
||||
dup = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
bl->max_conn = ngx_atoi(value[i].data + 2, value[i].len - 2);
|
||||
if (bl->max_conn == NGX_ERROR) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
bl->max_busy = ngx_atoi(value[i].data + 2, value[i].len - 2);
|
||||
if (bl->max_busy == NGX_ERROR) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value[i].len > 2 && ngx_strncasecmp(value[i].data, "w:", 2) == 0) {
|
||||
case 'w':
|
||||
if (bl->max_waiting) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"duplicate \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
dup = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
bl->max_waiting = ngx_atoi(value[i].data + 2, value[i].len - 2);
|
||||
if (bl->max_waiting == NGX_ERROR) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
case 't':
|
||||
if (bl->timeout) {
|
||||
dup = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
line.len = value[i].len - 2;
|
||||
line.data = value[i].data + 2;
|
||||
|
||||
bl->timeout = ngx_parse_time(&line, 1);
|
||||
if (bl->timeout == NGX_ERROR) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
default:
|
||||
invalid = 1;
|
||||
}
|
||||
|
||||
if (bl->timeout) {
|
||||
if (dup) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"duplicate timeout \"%s\"", value[i].data);
|
||||
"duplicate value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
bl->timeout = ngx_parse_time(&value[1], 1);
|
||||
if (bl->timeout == NGX_ERROR) {
|
||||
if (invalid) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid timeout \"%s\"", value[i].data);
|
||||
"invalid value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (bl->timeout == 0 && bl->max_waiting) {
|
||||
ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
|
||||
"busy lock waiting is useless with zero timeout");
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
@ -4,20 +4,21 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_event.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
u_char *busy_mask;
|
||||
char *busy;
|
||||
int busy_n;
|
||||
u_char *md5_mask;
|
||||
char *md5;
|
||||
int cachable;
|
||||
|
||||
int waiting_n;
|
||||
int busy;
|
||||
int max_busy;
|
||||
|
||||
int waiting;
|
||||
int max_waiting;
|
||||
|
||||
int conn_n;
|
||||
int max_conn;
|
||||
|
||||
time_t timeout;
|
||||
|
||||
/* ngx_mutex_t mutex; */
|
||||
@ -25,7 +26,21 @@ typedef struct {
|
||||
} ngx_http_busy_lock_t;
|
||||
|
||||
|
||||
int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, u_char *md5);
|
||||
typedef struct {
|
||||
time_t time;
|
||||
ngx_event_t *event;
|
||||
void (*event_handler)(ngx_event_t *ev);
|
||||
u_char *md5;
|
||||
int slot;
|
||||
} ngx_http_busy_lock_ctx_t;
|
||||
|
||||
|
||||
int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc);
|
||||
int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
|
||||
ngx_http_busy_lock_ctx_t *bc, int lock);
|
||||
void ngx_http_busy_unlock_cachable(ngx_http_busy_lock_t *bl,
|
||||
ngx_http_busy_lock_ctx_t *bc);
|
||||
|
||||
char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
|
@ -8,10 +8,7 @@
|
||||
|
||||
int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx)
|
||||
{
|
||||
ssize_t n;
|
||||
MD5_CTX md5;
|
||||
ngx_err_t err;
|
||||
ngx_http_cache_header_t *h;
|
||||
MD5_CTX md5;
|
||||
|
||||
ctx->header_size = sizeof(ngx_http_cache_header_t) + ctx->key.len + 1;
|
||||
|
||||
@ -38,6 +35,19 @@ ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data);
|
||||
|
||||
/* TODO: look open files cache */
|
||||
|
||||
return ngx_http_cache_open_file(r, ctx, 0);
|
||||
}
|
||||
|
||||
|
||||
/* TODO: Win32 inode analogy */
|
||||
|
||||
int ngx_http_cache_open_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx,
|
||||
ngx_file_uniq_t uniq)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_err_t err;
|
||||
ngx_http_cache_header_t *h;
|
||||
|
||||
ctx->file.fd = ngx_open_file(ctx->file.name.data,
|
||||
NGX_FILE_RDONLY, NGX_FILE_OPEN);
|
||||
|
||||
@ -53,6 +63,25 @@ ngx_log_debug(r->connection->log, "FILE: %s" _ ctx->file.name.data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (uniq) {
|
||||
if (ngx_stat_fd(ctx->file.fd, &ctx->file.info) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
|
||||
ngx_stat_fd_n " \"%s\" failed", ctx->file.name.data);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_file_uniq(ctx->file.info) == uniq) {
|
||||
if (ngx_close_file(ctx->file.fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
|
||||
ngx_close_file_n " \"%s\" failed",
|
||||
ctx->file.name.data);
|
||||
}
|
||||
|
||||
return NGX_HTTP_CACHE_THE_SAME;
|
||||
}
|
||||
}
|
||||
|
||||
n = ngx_read_file(&ctx->file, ctx->buf->pos,
|
||||
ctx->buf->end - ctx->buf->last, 0);
|
||||
|
||||
|
@ -13,7 +13,7 @@ typedef struct {
|
||||
time_t date;
|
||||
off_t length;
|
||||
size_t key_len;
|
||||
char key[0];
|
||||
char key[1];
|
||||
} ngx_http_cache_header_t;
|
||||
|
||||
|
||||
@ -46,11 +46,14 @@ typedef struct {
|
||||
} ngx_http_cache_ctx_t;
|
||||
|
||||
|
||||
#define NGX_HTTP_CACHE_STALE 1
|
||||
#define NGX_HTTP_CACHE_AGED 2
|
||||
#define NGX_HTTP_CACHE_STALE 1
|
||||
#define NGX_HTTP_CACHE_AGED 2
|
||||
#define NGX_HTTP_CACHE_THE_SAME 3
|
||||
|
||||
|
||||
int ngx_http_cache_get_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx);
|
||||
int ngx_http_cache_open_file(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx,
|
||||
ngx_file_uniq_t uniq);
|
||||
int ngx_http_cache_update_file(ngx_http_request_t *r,ngx_http_cache_ctx_t *ctx,
|
||||
ngx_str_t *temp_file);
|
||||
|
||||
|
@ -47,6 +47,8 @@ typedef struct {
|
||||
#define ngx_http_get_module_srv_conf(r, module) r->srv_conf[module.ctx_index]
|
||||
#define ngx_http_get_module_loc_conf(r, module) r->loc_conf[module.ctx_index]
|
||||
|
||||
#define ngx_http_conf_module_main_conf(cf, module) \
|
||||
((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
|
||||
|
||||
|
||||
extern int (*ngx_http_top_header_filter) (ngx_http_request_t *r);
|
||||
|
@ -31,6 +31,7 @@ static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
|
||||
static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_set_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_set_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
|
||||
static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data);
|
||||
@ -192,6 +193,13 @@ static ngx_command_t ngx_http_core_commands[] = {
|
||||
offsetof(ngx_http_core_loc_conf_t, msie_padding),
|
||||
NULL},
|
||||
|
||||
{ngx_string("error_page"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
|
||||
ngx_set_error_page,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
0,
|
||||
NULL},
|
||||
|
||||
{ngx_string("error_log"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_set_error_log,
|
||||
@ -631,8 +639,8 @@ static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
|
||||
char *rv;
|
||||
ngx_str_t *location;
|
||||
ngx_http_module_t *module;
|
||||
ngx_conf_t pcf;
|
||||
ngx_http_conf_ctx_t *ctx, *pctx;
|
||||
ngx_conf_t pvcf;
|
||||
ngx_http_conf_ctx_t *ctx, *pvctx;
|
||||
ngx_http_core_srv_conf_t *cscf;
|
||||
ngx_http_core_loc_conf_t *clcf, **clcfp;
|
||||
|
||||
@ -640,9 +648,9 @@ static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
|
||||
ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
|
||||
NGX_CONF_ERROR);
|
||||
|
||||
pctx = (ngx_http_conf_ctx_t *) cf->ctx;
|
||||
ctx->main_conf = pctx->main_conf;
|
||||
ctx->srv_conf = pctx->srv_conf;
|
||||
pvctx = (ngx_http_conf_ctx_t *) cf->ctx;
|
||||
ctx->main_conf = pvctx->main_conf;
|
||||
ctx->srv_conf = pvctx->srv_conf;
|
||||
|
||||
ngx_test_null(ctx->loc_conf,
|
||||
ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
|
||||
@ -672,11 +680,11 @@ static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
|
||||
ngx_test_null(clcfp, ngx_push_array(&cscf->locations), NGX_CONF_ERROR);
|
||||
*clcfp = clcf;
|
||||
|
||||
pcf = *cf;
|
||||
pvcf = *cf;
|
||||
cf->ctx = ctx;
|
||||
cf->cmd_type = NGX_HTTP_LOC_CONF;
|
||||
rv = ngx_conf_parse(cf, NULL);
|
||||
*cf = pcf;
|
||||
*cf = pvcf;
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -856,6 +864,7 @@ static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf)
|
||||
lcf->default_type.len = 0;
|
||||
lcf->default_type.data = NULL;
|
||||
lcf->err_log = NULL;
|
||||
lcf->error_pages = NULL;
|
||||
|
||||
*/
|
||||
|
||||
@ -929,6 +938,10 @@ static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
|
||||
}
|
||||
}
|
||||
|
||||
if (conf->error_pages == NULL && prev->error_pages) {
|
||||
conf->error_pages = prev->error_pages;
|
||||
}
|
||||
|
||||
ngx_conf_merge_str_value(conf->default_type,
|
||||
prev->default_type, "text/plain");
|
||||
|
||||
@ -1061,6 +1074,47 @@ static char *ngx_set_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_set_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_core_loc_conf_t *lcf = conf;
|
||||
|
||||
int i;
|
||||
ngx_str_t *value;
|
||||
ngx_http_err_page_t *err;
|
||||
|
||||
if (lcf->error_pages == NULL) {
|
||||
lcf->error_pages = ngx_create_array(cf->pool, 5,
|
||||
sizeof(ngx_http_err_page_t));
|
||||
if (lcf->error_pages == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
for (i = 1; i < cf->args->nelts - 1; i++) {
|
||||
ngx_test_null(err, ngx_push_array(lcf->error_pages), NGX_CONF_ERROR);
|
||||
err->code = ngx_atoi(value[i].data, value[i].len);
|
||||
if (err->code == NGX_ERROR) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (err->code < 400 || err->code > 599) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"value \"%s\" must be between 400 and 599",
|
||||
value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
err->uri = value[cf->args->nelts - 1];
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_core_loc_conf_t *lcf = conf;
|
||||
@ -1079,10 +1133,10 @@ static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
|
||||
static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data)
|
||||
{
|
||||
int *np = data;
|
||||
|
||||
#if (HAVE_LOWAT_EVENT)
|
||||
|
||||
int *np = data;
|
||||
|
||||
if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"\"send_lowat\" must be less than %d "
|
||||
|
@ -99,6 +99,12 @@ typedef struct {
|
||||
} ngx_http_type_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
ngx_str_t uri;
|
||||
} ngx_http_err_page_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name; /* location name */
|
||||
void **loc_conf ; /* pointer to the modules' loc_conf */
|
||||
@ -120,6 +126,7 @@ typedef struct {
|
||||
ngx_msec_t lingering_timeout; /* lingering_timeout */
|
||||
|
||||
int msie_padding; /* msie_padding */
|
||||
ngx_array_t *error_pages; /* error_page */
|
||||
|
||||
ngx_log_t *err_log;
|
||||
} ngx_http_core_loc_conf_t;
|
||||
|
@ -90,8 +90,9 @@ static ngx_str_t http_codes[] = {
|
||||
static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
int len, status, i;
|
||||
char *p;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t *ch;
|
||||
ngx_chain_t *ln;
|
||||
ngx_table_elt_t *header;
|
||||
|
||||
if (r->http_version < NGX_HTTP_VERSION_10) {
|
||||
@ -149,7 +150,7 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
len += r->headers_out.date->key.len
|
||||
+ r->headers_out.date->value.len + 2;
|
||||
} else {
|
||||
len += sizeof("Date: Mon, 28 Sep 1970 00:00:00 GMT" CRLF) - 1;
|
||||
len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
|
||||
}
|
||||
|
||||
if (r->headers_out.content_length == NULL) {
|
||||
@ -174,7 +175,7 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
&& r->headers_out.location->value.data[0] == '/')
|
||||
{
|
||||
r->headers_out.location->key.len = 0;
|
||||
len += sizeof("Location: http://") - 1,
|
||||
len += sizeof("Location: http://") - 1
|
||||
+ r->server_name->len + r->headers_out.location->value.len + 2;
|
||||
|
||||
if (r->port != 80) {
|
||||
@ -187,7 +188,7 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
+ r->headers_out.last_modified->value.len + 2;
|
||||
|
||||
} else if (r->headers_out.last_modified_time != -1) {
|
||||
len += sizeof("Last-Modified: Mon, 28 Sep 1970 00:00:00 GMT" CRLF) - 1;
|
||||
len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
|
||||
}
|
||||
|
||||
if (r->chunked) {
|
||||
@ -210,7 +211,9 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
len += header[i].key.len + 2 + header[i].value.len + 2;
|
||||
}
|
||||
|
||||
ngx_test_null(h, ngx_create_temp_hunk(r->pool, len), NGX_ERROR);
|
||||
if (!(h = ngx_create_temp_hunk(r->pool, len))) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* "HTTP/1.x " */
|
||||
h->last = ngx_cpymem(h->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1);
|
||||
@ -232,30 +235,70 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
|
||||
if (!(r->headers_out.date && r->headers_out.date->key.len)) {
|
||||
h->last = ngx_cpymem(h->last, "Date: ", sizeof("Date: ") - 1);
|
||||
h->last += ngx_http_get_time(h->last, time(NULL));
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
p = h->last;
|
||||
#endif
|
||||
h->last += ngx_http_get_time(h->last, ngx_time());
|
||||
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
r->headers_out.date = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
|
||||
if (r->headers_out.date == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_out.date->key.len = 0;
|
||||
r->headers_out.date->key.data = NULL;
|
||||
r->headers_out.date->value.len = h->last - p;
|
||||
r->headers_out.date->value.data = p;
|
||||
#endif
|
||||
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
if (r->headers_out.content_length == NULL) {
|
||||
if (r->headers_out.content_length_n >= 0) {
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
p = h->last + sizeof("Content-Length: ") - 1;
|
||||
#endif
|
||||
h->last += ngx_snprintf(h->last, /* 2^64 */
|
||||
sizeof("Content-Length: 18446744073709551616" CRLF),
|
||||
"Content-Length: " OFF_FMT CRLF,
|
||||
r->headers_out.content_length_n);
|
||||
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
r->headers_out.content_length = ngx_palloc(r->pool,
|
||||
sizeof(ngx_table_elt_t));
|
||||
if (r->headers_out.content_length == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_out.content_length->key.len = 0;
|
||||
r->headers_out.content_length->key.data = NULL;
|
||||
r->headers_out.content_length->value.len = h->last - p - 2;
|
||||
r->headers_out.content_length->value.data = p;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
|
||||
h->last = ngx_cpymem(h->last, "Content-Type: ",
|
||||
sizeof("Content-Type: ") - 1);
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
p = h->last;
|
||||
#endif
|
||||
h->last = ngx_cpymem(h->last, r->headers_out.content_type->value.data,
|
||||
r->headers_out.content_type->value.len);
|
||||
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
if (r->headers_out.charset.len) {
|
||||
h->last = ngx_cpymem(h->last, "; charset=",
|
||||
sizeof("; charset=") - 1);
|
||||
h->last = ngx_cpymem(h->last, r->headers_out.charset.data,
|
||||
r->headers_out.charset.len);
|
||||
|
||||
r->headers_out.content_type->value.len = h->last - p;
|
||||
r->headers_out.content_type->value.data = p;
|
||||
#endif
|
||||
}
|
||||
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
@ -265,6 +308,7 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
&& r->headers_out.location->value.len
|
||||
&& r->headers_out.location->value.data[0] == '/')
|
||||
{
|
||||
p = h->last + sizeof("Location: ") - 1;
|
||||
h->last = ngx_cpymem(h->last, "Location: http://",
|
||||
sizeof("Location: http://") - 1);
|
||||
h->last = ngx_cpymem(h->last, r->server_name->data,
|
||||
@ -277,6 +321,9 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
h->last = ngx_cpymem(h->last, r->headers_out.location->value.data,
|
||||
r->headers_out.location->value.len);
|
||||
|
||||
r->headers_out.location->value.len = h->last - p;
|
||||
r->headers_out.location->value.data = p;
|
||||
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
@ -285,8 +332,25 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
{
|
||||
h->last = ngx_cpymem(h->last, "Last-Modified: ",
|
||||
sizeof("Last-Modified: ") - 1);
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
p = h->last;
|
||||
#endif
|
||||
h->last += ngx_http_get_time(h->last,
|
||||
r->headers_out.last_modified_time);
|
||||
r->headers_out.last_modified_time);
|
||||
|
||||
#if (NGX_HTTP_LOG_ALL_HEADERS_OUT)
|
||||
r->headers_out.last_modified = ngx_palloc(r->pool,
|
||||
sizeof(ngx_table_elt_t));
|
||||
if (r->headers_out.last_modified == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_out.last_modified->key.len = 0;
|
||||
r->headers_out.last_modified->key.data = NULL;
|
||||
r->headers_out.last_modified->value.len = h->last - p;
|
||||
r->headers_out.last_modified->value.data = p;
|
||||
#endif
|
||||
|
||||
*(h->last++) = CR; *(h->last++) = LF;
|
||||
}
|
||||
|
||||
@ -329,12 +393,14 @@ static int ngx_http_header_filter(ngx_http_request_t *r)
|
||||
h->type |= NGX_HUNK_LAST;
|
||||
}
|
||||
|
||||
ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR);
|
||||
if (!(ln = ngx_alloc_chain_link(r->pool))) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ch->hunk = h;
|
||||
ch->next = NULL;
|
||||
ln->hunk = h;
|
||||
ln->next = NULL;
|
||||
|
||||
return ngx_http_write_filter(r, ch);
|
||||
return ngx_http_write_filter(r, ln);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,6 +10,7 @@ ngx_http_header_t ngx_http_headers_in[] = {
|
||||
{ ngx_string("If-Modified-Since"),
|
||||
offsetof(ngx_http_headers_in_t, if_modified_since) },
|
||||
{ ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
|
||||
{ ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer) },
|
||||
|
||||
{ ngx_string("Content-Length"),
|
||||
offsetof(ngx_http_headers_in_t, content_length) },
|
||||
|
773
src/http/ngx_http_log_handler.c
Normal file
773
src/http/ngx_http_log_handler.c
Normal file
@ -0,0 +1,773 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include <nginx.h>
|
||||
|
||||
|
||||
static char *ngx_http_log_addr(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_connection(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_pipe(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_time(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_request(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_status(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_length(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_header_in(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_unknown_header_in(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_header_out(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
static char *ngx_http_log_unknown_header_out(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
|
||||
static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
|
||||
static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
|
||||
static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
|
||||
void *child);
|
||||
static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static int ngx_http_log_parse_format(ngx_conf_t *cf, ngx_array_t *ops,
|
||||
ngx_str_t *line);
|
||||
|
||||
|
||||
static ngx_command_t ngx_http_log_commands[] = {
|
||||
|
||||
{ngx_string("log_format"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
|
||||
ngx_http_log_set_format,
|
||||
NGX_HTTP_MAIN_CONF_OFFSET,
|
||||
0,
|
||||
NULL},
|
||||
|
||||
{ngx_string("access_log"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
|
||||
ngx_http_log_set_log,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
0,
|
||||
NULL},
|
||||
|
||||
ngx_null_command
|
||||
};
|
||||
|
||||
|
||||
ngx_http_module_t ngx_http_log_module_ctx = {
|
||||
ngx_http_log_create_main_conf, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
ngx_http_log_create_loc_conf, /* create location configration */
|
||||
ngx_http_log_merge_loc_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 */
|
||||
NULL /* init child */
|
||||
};
|
||||
|
||||
|
||||
static ngx_str_t http_access_log = ngx_string("access.log");
|
||||
|
||||
|
||||
static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
static ngx_str_t ngx_http_combined_fmt =
|
||||
ngx_string("%addr - - [%time] \"%request\" %status %length "
|
||||
"\"%{Referer}i\" %{User-Agent}i\"");
|
||||
|
||||
|
||||
static ngx_http_log_op_name_t ngx_http_log_fmt_ops[] = {
|
||||
{ ngx_string("addr"), INET_ADDRSTRLEN - 1, ngx_http_log_addr },
|
||||
{ ngx_string("conn"), NGX_INT32_LEN, ngx_http_log_connection },
|
||||
{ ngx_string("pipe"), 1, ngx_http_log_pipe },
|
||||
{ ngx_string("time"), sizeof("28/Sep/1970:12:00:00") - 1,
|
||||
ngx_http_log_time },
|
||||
{ ngx_string("request"), 0, ngx_http_log_request },
|
||||
{ ngx_string("status"), 3, ngx_http_log_status },
|
||||
{ ngx_string("length"), NGX_OFF_LEN, ngx_http_log_length },
|
||||
{ ngx_string("i"), NGX_HTTP_LOG_ARG, ngx_http_log_header_in },
|
||||
{ ngx_string("o"), NGX_HTTP_LOG_ARG, ngx_http_log_header_out },
|
||||
{ ngx_null_string, 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
int ngx_http_log_handler(ngx_http_request_t *r)
|
||||
{
|
||||
int i, l;
|
||||
u_int data;
|
||||
char *line, *p;
|
||||
size_t len;
|
||||
ngx_http_log_t *log;
|
||||
ngx_http_log_op_t *op;
|
||||
ngx_http_log_loc_conf_t *lcf;
|
||||
#if (WIN32)
|
||||
u_int written;
|
||||
#endif
|
||||
|
||||
ngx_log_debug(r->connection->log, "log handler");
|
||||
|
||||
lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
|
||||
|
||||
log = lcf->logs->elts;
|
||||
for (l = 0; l < lcf->logs->nelts; l++) {
|
||||
|
||||
len = 0;
|
||||
op = log[l].ops->elts;
|
||||
for (i = 0; i < log[l].ops->nelts; i++) {
|
||||
if (op[i].len == 0) {
|
||||
len += (size_t) op[i].op(r, NULL, op[i].data);
|
||||
|
||||
} else {
|
||||
len += op[i].len;
|
||||
}
|
||||
}
|
||||
|
||||
#if (WIN32)
|
||||
len += 2;
|
||||
#else
|
||||
len++;
|
||||
#endif
|
||||
|
||||
ngx_test_null(line, ngx_palloc(r->pool, len), NGX_ERROR);
|
||||
p = line;
|
||||
|
||||
for (i = 0; i < log[l].ops->nelts; i++) {
|
||||
if (op[i].op == NGX_HTTP_LOG_COPY_SHORT) {
|
||||
len = op[i].len;
|
||||
data = op[i].data;
|
||||
while (len--) {
|
||||
*p++ = data & 0xff;
|
||||
data >>= 8;
|
||||
}
|
||||
|
||||
} else if (op[i].op == NGX_HTTP_LOG_COPY_LONG) {
|
||||
p = ngx_cpymem(p, (void *) op[i].data, op[i].len);
|
||||
|
||||
} else {
|
||||
p = op[i].op(r, p, op[i].data);
|
||||
}
|
||||
}
|
||||
|
||||
#if (WIN32)
|
||||
*p++ = CR; *p++ = LF;
|
||||
WriteFile(log[l].file->fd, line, p - line, &written, NULL);
|
||||
#else
|
||||
*p++ = LF;
|
||||
write(log[l].file->fd, line, p - line);
|
||||
#endif
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_addr(ngx_http_request_t *r, char *buf, uintptr_t data)
|
||||
{
|
||||
return ngx_cpymem(buf, r->connection->addr_text.data,
|
||||
r->connection->addr_text.len);
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_connection(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
return buf + ngx_snprintf(buf, NGX_INT32_LEN + 1, "%u",
|
||||
r->connection->number);
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_pipe(ngx_http_request_t *r, char *buf, uintptr_t data)
|
||||
{
|
||||
if (r->pipeline) {
|
||||
*buf = 'p';
|
||||
} else {
|
||||
*buf = '.';
|
||||
}
|
||||
|
||||
return buf + 1;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_time(ngx_http_request_t *r, char *buf, uintptr_t data)
|
||||
{
|
||||
ngx_tm_t tm;
|
||||
|
||||
ngx_localtime(&tm);
|
||||
|
||||
return buf + ngx_snprintf(buf, sizeof("28/Sep/1970:12:00:00"),
|
||||
"%02d/%s/%d:%02d:%02d:%02d",
|
||||
tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1],
|
||||
tm.ngx_tm_year,
|
||||
tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec);
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_request(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
if (buf == NULL) {
|
||||
/* find the request line length */
|
||||
return (char *) r->request_line.len;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, r->request_line.data, r->request_line.len);
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_status(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
return buf + ngx_snprintf(buf, 4, "%d", r->headers_out.status);
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_length(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
return buf + ngx_snprintf(buf, NGX_OFF_LEN + 1, OFF_FMT,
|
||||
r->connection->sent);
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_header_in(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
int i;
|
||||
ngx_str_t *s;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_http_log_op_t *op;
|
||||
|
||||
if (r) {
|
||||
h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data);
|
||||
|
||||
if (h == NULL) {
|
||||
|
||||
/* no header */
|
||||
|
||||
if (buf) {
|
||||
*buf = '-';
|
||||
}
|
||||
|
||||
return buf + 1;
|
||||
}
|
||||
|
||||
if (buf == NULL) {
|
||||
/* find the header length */
|
||||
return (char *) h->value.len;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, h->value.data, h->value.len);
|
||||
}
|
||||
|
||||
/* find an offset while a format string compilation */
|
||||
|
||||
op = (ngx_http_log_op_t *) buf;
|
||||
s = (ngx_str_t *) data;
|
||||
|
||||
op->len = 0;
|
||||
|
||||
for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) {
|
||||
if (ngx_http_headers_in[i].name.len != s->len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncasecmp(ngx_http_headers_in[i].name.data, s->data, s->len)
|
||||
== 0)
|
||||
{
|
||||
op->op = ngx_http_log_header_in;
|
||||
op->data = ngx_http_headers_in[i].offset;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
op->op = ngx_http_log_unknown_header_in;
|
||||
op->data = (uintptr_t) s;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_unknown_header_in(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
int i;
|
||||
ngx_str_t *s;
|
||||
ngx_table_elt_t *h;
|
||||
|
||||
s = (ngx_str_t *) data;
|
||||
|
||||
h = r->headers_in.headers->elts;
|
||||
for (i = 0; i < r->headers_in.headers->nelts; i++) {
|
||||
if (h[i].key.len != s->len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncasecmp(h[i].key.data, s->data, s->len) == 0) {
|
||||
if (buf == NULL) {
|
||||
/* find the header length */
|
||||
return (char *) h[i].value.len;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, h[i].value.data, h[i].value.len);
|
||||
}
|
||||
}
|
||||
|
||||
/* no header */
|
||||
|
||||
if (buf) {
|
||||
*buf = '-';
|
||||
}
|
||||
|
||||
return buf + 1;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_header_out(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
int i;
|
||||
ngx_str_t *s;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_http_log_op_t *op;
|
||||
|
||||
if (r) {
|
||||
h = *(ngx_table_elt_t **) ((char *) &r->headers_out + data);
|
||||
|
||||
if (h == NULL) {
|
||||
|
||||
/* no header */
|
||||
|
||||
if (data == offsetof(ngx_http_headers_out_t, server)) {
|
||||
if (buf == NULL) {
|
||||
return (char *) (sizeof(NGINX_VER) - 1);
|
||||
}
|
||||
return ngx_cpymem(buf, NGINX_VER, sizeof(NGINX_VER) - 1);
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
*buf = '-';
|
||||
}
|
||||
|
||||
return buf + 1;
|
||||
}
|
||||
|
||||
if (buf == NULL) {
|
||||
/* find the header length */
|
||||
return (char *) h->value.len;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, h->value.data, h->value.len);
|
||||
}
|
||||
|
||||
/* find an offset while a format string compilation */
|
||||
|
||||
op = (ngx_http_log_op_t *) buf;
|
||||
s = (ngx_str_t *) data;
|
||||
|
||||
op->len = 0;
|
||||
|
||||
for (i = 0; ngx_http_headers_out[i].name.len != 0; i++) {
|
||||
if (ngx_http_headers_out[i].name.len != s->len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncasecmp(ngx_http_headers_out[i].name.data, s->data, s->len)
|
||||
== 0)
|
||||
{
|
||||
op->op = ngx_http_log_header_out;
|
||||
op->data = ngx_http_headers_out[i].offset;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
op->op = ngx_http_log_unknown_header_out;
|
||||
op->data = (uintptr_t) s;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_unknown_header_out(ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data)
|
||||
{
|
||||
int i;
|
||||
ngx_str_t *s;
|
||||
ngx_table_elt_t *h;
|
||||
|
||||
s = (ngx_str_t *) data;
|
||||
|
||||
h = r->headers_out.headers->elts;
|
||||
for (i = 0; i < r->headers_out.headers->nelts; i++) {
|
||||
if (h[i].key.len != s->len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_strncasecmp(h[i].key.data, s->data, s->len) == 0) {
|
||||
if (buf == NULL) {
|
||||
/* find the header length */
|
||||
return (char *) h[i].value.len;
|
||||
}
|
||||
|
||||
return ngx_cpymem(buf, h[i].value.data, h[i].value.len);
|
||||
}
|
||||
}
|
||||
|
||||
/* no header */
|
||||
|
||||
if (buf) {
|
||||
*buf = '-';
|
||||
}
|
||||
|
||||
return buf + 1;
|
||||
}
|
||||
|
||||
|
||||
static void *ngx_http_log_create_main_conf(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_http_log_main_conf_t *conf;
|
||||
|
||||
char *rc;
|
||||
ngx_str_t *value;
|
||||
|
||||
if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t)))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_init_array(conf->formats, cf->pool, 5, sizeof(ngx_http_log_fmt_t),
|
||||
NGX_CONF_ERROR);
|
||||
|
||||
cf->args->nelts = 0;
|
||||
|
||||
if (!(value = ngx_push_array(cf->args))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (!(value = ngx_push_array(cf->args))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
value->len = sizeof("combined") - 1;
|
||||
value->data = "combined";
|
||||
|
||||
if (!(value = ngx_push_array(cf->args))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
*value = ngx_http_combined_fmt;
|
||||
|
||||
rc = ngx_http_log_set_format(cf, NULL, conf);
|
||||
if (rc != NGX_CONF_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf)
|
||||
{
|
||||
ngx_http_log_loc_conf_t *conf;
|
||||
|
||||
ngx_test_null(conf, ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t)),
|
||||
NGX_CONF_ERROR);
|
||||
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
|
||||
void *child)
|
||||
{
|
||||
ngx_http_log_loc_conf_t *prev = parent;
|
||||
ngx_http_log_loc_conf_t *conf = child;
|
||||
|
||||
ngx_http_log_t *log;
|
||||
ngx_http_log_fmt_t *fmt;
|
||||
ngx_http_log_main_conf_t *lmcf;
|
||||
|
||||
if (conf->logs == NULL) {
|
||||
if (prev->logs) {
|
||||
conf->logs = prev->logs;
|
||||
|
||||
} else {
|
||||
|
||||
conf->logs = ngx_create_array(cf->pool, 2, sizeof(ngx_http_log_t));
|
||||
if (conf->logs == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (!(log = ngx_push_array(conf->logs))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
log->file = ngx_conf_open_file(cf->cycle, &http_access_log);
|
||||
if (log->file == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
lmcf = ngx_http_conf_module_main_conf(cf, ngx_http_log_module);
|
||||
fmt = lmcf->formats.elts;
|
||||
/* the default "combined" format */
|
||||
log->ops = fmt[0].ops;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
ngx_http_log_loc_conf_t *llcf = conf;
|
||||
|
||||
int i;
|
||||
ngx_str_t *value, name;
|
||||
ngx_http_log_t *log;
|
||||
ngx_http_log_fmt_t *fmt;
|
||||
ngx_http_log_main_conf_t *lmcf;
|
||||
|
||||
if (llcf->logs == NULL) {
|
||||
if (!(llcf->logs = ngx_create_array(cf->pool, 2,
|
||||
sizeof(ngx_http_log_t)))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
lmcf = ngx_http_conf_module_main_conf(cf, ngx_http_log_module);
|
||||
|
||||
if (!(log = ngx_push_array(llcf->logs))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (!(log->file = ngx_conf_open_file(cf->cycle, &value[1]))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (cf->args->nelts == 3) {
|
||||
name = value[2];
|
||||
} else {
|
||||
name.len = sizeof("combined") - 1;
|
||||
name.data = "combined";
|
||||
}
|
||||
|
||||
fmt = lmcf->formats.elts;
|
||||
for (i = 0; i < lmcf->formats.nelts; i++) {
|
||||
if (fmt[i].name.len == name.len
|
||||
&& ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
|
||||
{
|
||||
log->ops = fmt[i].ops;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf)
|
||||
{
|
||||
ngx_http_log_main_conf_t *lmcf = conf;
|
||||
|
||||
int s, f, invalid;
|
||||
char *data, *p, *fname;
|
||||
size_t i, len, fname_len;
|
||||
ngx_str_t *value, arg, *a;
|
||||
ngx_http_log_op_t *op;
|
||||
ngx_http_log_fmt_t *fmt;
|
||||
ngx_http_log_op_name_t *name;
|
||||
|
||||
value = cf->args->elts;
|
||||
#if 0
|
||||
lmcf = ngx_http_conf_module_main_conf(cf, ngx_http_log_module);
|
||||
#endif
|
||||
|
||||
fmt = lmcf->formats.elts;
|
||||
for (f = 0; f < lmcf->formats.nelts; f++) {
|
||||
if (fmt[f].name.len == value[1].len
|
||||
&& ngx_strcmp(fmt->name.data, value[1].data) == 0)
|
||||
{
|
||||
return "duplicate \"log_format\" name";
|
||||
}
|
||||
}
|
||||
|
||||
if (!(fmt = ngx_push_array(&lmcf->formats))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
fmt->name = value[1];
|
||||
|
||||
if (!(fmt->ops = ngx_create_array(cf->pool, 20,
|
||||
sizeof(ngx_http_log_op_t)))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
invalid = 0;
|
||||
data = NULL;
|
||||
|
||||
for (s = 2; s < cf->args->nelts && !invalid; s++) {
|
||||
|
||||
i = 0;
|
||||
|
||||
while (i < value[s].len) {
|
||||
|
||||
if (!(op = ngx_push_array(fmt->ops))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
data = &value[s].data[i];
|
||||
|
||||
if (value[s].data[i] == '%') {
|
||||
i++;
|
||||
|
||||
if (i == value[s].len) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (value[s].data[i] == '{') {
|
||||
i++;
|
||||
|
||||
arg.data = &value[s].data[i];
|
||||
|
||||
while (i < value[s].len && value[s].data[i] != '}') {
|
||||
i++;
|
||||
}
|
||||
|
||||
arg.len = &value[s].data[i] - arg.data;
|
||||
|
||||
if (i == value[s].len || arg.len == 0) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
} else {
|
||||
arg.len = 0;
|
||||
}
|
||||
|
||||
fname = &value[s].data[i];
|
||||
|
||||
while (i < value[s].len
|
||||
&& value[s].data[i] >= 'a'
|
||||
&& value[s].data[i] <= 'z')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
fname_len = &value[s].data[i] - fname;
|
||||
|
||||
if (fname_len == 0) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
for (name = ngx_http_log_fmt_ops; name->name.len; name++) {
|
||||
if (name->name.len == fname_len
|
||||
&& ngx_strncmp(name->name.data, fname, fname_len) == 0)
|
||||
{
|
||||
if (name->len != NGX_HTTP_LOG_ARG) {
|
||||
if (arg.len) {
|
||||
fname[fname_len] = '\0';
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"\"%s\" must not have argument",
|
||||
data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
op->len = name->len;
|
||||
op->op = name->op;
|
||||
op->data = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (arg.len == 0) {
|
||||
fname[fname_len] = '\0';
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"\"%s\" requires argument",
|
||||
data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (!(a = ngx_palloc(cf->pool, sizeof(ngx_str_t)))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
*a = arg;
|
||||
name->op(NULL, (char *) op, (uintptr_t) a);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name->name.len == 0) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
i++;
|
||||
|
||||
while (i < value[s].len && value[s].data[i] != '%') {
|
||||
i++;
|
||||
}
|
||||
|
||||
len = &value[s].data[i] - data;
|
||||
|
||||
if (len) {
|
||||
|
||||
op->len = len;
|
||||
|
||||
if (len <= sizeof(uintptr_t)) {
|
||||
op->op = NGX_HTTP_LOG_COPY_SHORT;
|
||||
op->data = 0;
|
||||
|
||||
while (len--) {
|
||||
op->data <<= 8;
|
||||
op->data |= data[len];
|
||||
}
|
||||
|
||||
} else {
|
||||
op->op = NGX_HTTP_LOG_COPY_LONG;
|
||||
|
||||
if (!(p = ngx_palloc(cf->pool, len))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(p, data, len);
|
||||
op->data = (uintptr_t) p;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid parameter \"%s\"", data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
59
src/http/ngx_http_log_handler.h
Normal file
59
src/http/ngx_http_log_handler.h
Normal file
@ -0,0 +1,59 @@
|
||||
#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 char *(*ngx_http_log_op_pt) (ngx_http_request_t *r, char *buf,
|
||||
uintptr_t data);
|
||||
|
||||
#define NGX_HTTP_LOG_COPY_SHORT (ngx_http_log_op_pt) 0
|
||||
#define NGX_HTTP_LOG_COPY_LONG (ngx_http_log_op_pt) -1
|
||||
|
||||
#define NGX_HTTP_LOG_ARG (u_int) -1
|
||||
|
||||
/* STUB */
|
||||
#define NGX_INT32_LEN sizeof("4294967296") - 1
|
||||
#define NGX_OFF_LEN sizeof("18446744073709551616") - 1
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
ngx_http_log_op_pt op;
|
||||
uintptr_t data;
|
||||
} ngx_http_log_op_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name;
|
||||
ngx_array_t *ops; /* array of ngx_http_log_op_t */
|
||||
} ngx_http_log_fmt_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name;
|
||||
size_t len;
|
||||
ngx_http_log_op_pt op;
|
||||
} ngx_http_log_op_name_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_array_t formats; /* array of ngx_http_log_fmt_t */
|
||||
} ngx_http_log_main_conf_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_open_file_t *file;
|
||||
ngx_array_t *ops; /* array of ngx_http_log_op_t */
|
||||
} ngx_http_log_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_array_t *logs; /* array of ngx_http_log_t */
|
||||
} ngx_http_log_loc_conf_t;
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_LOG_HANDLER_H_INCLUDED_ */
|
@ -225,6 +225,7 @@ ngx_log_debug(rev->log, "IN: %08x" _ in_port);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: ngx_init_table */
|
||||
if (!(r->headers_out.headers = ngx_create_table(r->pool, 20))) {
|
||||
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
ngx_http_close_connection(c);
|
||||
@ -416,6 +417,7 @@ static void ngx_http_process_request_line(ngx_event_t *rev)
|
||||
lctx = c->log->data;
|
||||
lctx->action = "reading client request headers";
|
||||
lctx->url = r->unparsed_uri.data;
|
||||
/* TODO: ngx_init_table */
|
||||
r->headers_in.headers = ngx_create_table(r->pool, 20);
|
||||
|
||||
if (cscf->large_client_header
|
||||
@ -1068,7 +1070,8 @@ static void ngx_http_set_keepalive(ngx_http_request_t *r)
|
||||
|
||||
if (h->pos < h->last) {
|
||||
|
||||
/* Pipelined request.
|
||||
/*
|
||||
* Pipelined request.
|
||||
*
|
||||
* We do not know here whether a pipelined request is complete
|
||||
* so if the large client headers are not enabled
|
||||
|
@ -74,6 +74,7 @@ typedef struct {
|
||||
ngx_table_elt_t *connection;
|
||||
ngx_table_elt_t *if_modified_since;
|
||||
ngx_table_elt_t *user_agent;
|
||||
ngx_table_elt_t *referer;
|
||||
|
||||
ngx_table_elt_t *content_length;
|
||||
ngx_table_elt_t *accept_encoding;
|
||||
@ -202,6 +203,8 @@ struct ngx_http_request_s {
|
||||
unsigned bypass_cache:1;
|
||||
unsigned no_cache:1;
|
||||
|
||||
unsigned error_page:1;
|
||||
|
||||
#if 0
|
||||
unsigned cachable:1;
|
||||
#endif
|
||||
|
@ -168,9 +168,10 @@ static ngx_str_t error_pages[] = {
|
||||
|
||||
int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
|
||||
{
|
||||
int err, rc;
|
||||
int err, rc, i;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t *out, **ll, *cl;
|
||||
ngx_http_err_page_t *err_page;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
rc = ngx_http_discard_body(r);
|
||||
@ -181,19 +182,6 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
|
||||
|
||||
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 + 3;
|
||||
|
||||
} else {
|
||||
/* 5XX */
|
||||
err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17;
|
||||
}
|
||||
|
||||
if (r->keepalive != 0) {
|
||||
switch (error) {
|
||||
case NGX_HTTP_BAD_REQUEST:
|
||||
@ -213,6 +201,31 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
|
||||
}
|
||||
}
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
|
||||
if (!r->error_page && clcf->error_pages) {
|
||||
err_page = clcf->error_pages->elts;
|
||||
for (i = 0; i < clcf->error_pages->nelts; i++) {
|
||||
if (err_page[i].code == error) {
|
||||
r->error_page = 1;
|
||||
return ngx_http_internal_redirect(r, &err_page[i].uri, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 + 3;
|
||||
|
||||
} else {
|
||||
/* 5XX */
|
||||
err = error - NGX_HTTP_INTERNAL_SERVER_ERROR + 3 + 17;
|
||||
}
|
||||
|
||||
if (error_pages[err].len) {
|
||||
r->headers_out.content_length_n = error_pages[err].len
|
||||
+ sizeof(error_tail) - 1
|
||||
@ -272,8 +285,6 @@ int ngx_http_special_response_handler(ngx_http_request_t *r, int error)
|
||||
ngx_alloc_link_and_set_hunk(cl, h, r->pool, NGX_ERROR);
|
||||
ngx_chain_add_link(out, ll, cl);
|
||||
|
||||
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
|
||||
|
||||
if (clcf->msie_padding
|
||||
&& r->http_version >= NGX_HTTP_VERSION_10
|
||||
&& error >= NGX_HTTP_BAD_REQUEST
|
||||
|
@ -63,6 +63,7 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
|
||||
#define ngx_is_file(sb) (S_ISREG(sb.st_mode))
|
||||
#define ngx_file_size(sb) sb.st_size
|
||||
#define ngx_file_mtime(sb) sb.st_mtime
|
||||
#define ngx_file_uniq(sb) sb.st_ino
|
||||
|
||||
|
||||
#endif /* _NGX_FILES_H_INCLUDED_ */
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
typedef int ngx_fd_t;
|
||||
typedef struct stat ngx_file_info_t;
|
||||
typedef ino_t ngx_file_uniq_t;
|
||||
|
||||
|
||||
|
||||
#endif /* _NGX_TYPES_H_INCLUDED_ */
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
/* INVALID_FILE_ATTRIBUTES specified but never defined at least in VC6SP2 */
|
||||
/* INVALID_FILE_ATTRIBUTES specified but not defined at least in MSVC6SP2 */
|
||||
#ifndef INVALID_FILE_ATTRIBUTES
|
||||
#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
|
||||
#endif
|
||||
@ -67,6 +67,7 @@ int ngx_file_type(char *filename, ngx_file_info_t *fi);
|
||||
#define ngx_file_size(fi) \
|
||||
(((off_t) fi.nFileSizeHigh << 32) | fi.nFileSizeLow)
|
||||
|
||||
#define ngx_file_uniq(fi) (*(ngx_file_uniq_t *) &fi.nFileIndexHigh)
|
||||
|
||||
/* There are 134774 days between 1 Jan 1970 and 1 Jan 1601,
|
||||
11644473600 seconds or 11644473600,000,000,0 100-nanosecond intervals */
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
#include <ngx_stat.h>
|
||||
|
||||
int ngx_file_type(char *file, ngx_file_info_t *sb)
|
||||
{
|
||||
|
@ -1,30 +0,0 @@
|
||||
#ifndef _NGX_STAT_H_INCLUDED_
|
||||
#define _NGX_STAT_H_INCLUDED_
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* INVALID_FILE_ATTRIBUTES specified but never defined at least in VC6SP2 */
|
||||
#ifndef INVALID_FILE_ATTRIBUTES
|
||||
#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
typedef BY_HANDLE_FILE_INFORMATION ngx_file_info_t;
|
||||
|
||||
|
||||
#define ngx_file_type_n "GetFileAttributes"
|
||||
|
||||
#define ngx_is_dir(fi) (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
|
||||
#define ngx_stat_n "GetFileAttributes"
|
||||
|
||||
#define ngx_fstat(file, fd, sb) ngx_stat(file, sb)
|
||||
#define ngx_fstat_n "GetFileAttributes"
|
||||
|
||||
|
||||
/*
|
||||
int ngx_stat(char *file, ngx_stat_t *sb);
|
||||
*/
|
||||
|
||||
|
||||
#endif /* _NGX_STAT_H_INCLUDED_ */
|
@ -6,21 +6,9 @@
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
typedef unsigned __int32 u_int32_t;
|
||||
typedef __int64 int64_t;
|
||||
|
||||
typedef int ssize_t;
|
||||
typedef long time_t;
|
||||
|
||||
typedef HANDLE ngx_fd_t;
|
||||
typedef unsigned __int64 off_t;
|
||||
typedef BY_HANDLE_FILE_INFORMATION ngx_file_info_t;
|
||||
|
||||
|
||||
#define OFF_FMT "%I64d"
|
||||
#define SIZE_FMT "%d"
|
||||
#define SIZEX_FMT "%x"
|
||||
#define PID_FMT "%d"
|
||||
typedef uint64_t ngx_file_uniq_t;
|
||||
|
||||
|
||||
#endif /* _NGX_TYPES_H_INCLUDED_ */
|
||||
|
@ -18,6 +18,30 @@
|
||||
#define ngx_inline __inline
|
||||
|
||||
|
||||
#if 0
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
#endif
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef u_int uintptr_t;
|
||||
|
||||
typedef int ssize_t;
|
||||
typedef long time_t;
|
||||
typedef unsigned __int64 off_t;
|
||||
|
||||
|
||||
#define OFF_FMT "%I64d"
|
||||
#define SIZE_FMT "%d"
|
||||
#define SIZEX_FMT "%x"
|
||||
#define PID_FMT "%d"
|
||||
|
||||
|
||||
/* STUB */
|
||||
typedef uint32_t u_int32_t;
|
||||
|
||||
|
||||
#ifndef HAVE_INHERITED_NONBLOCK
|
||||
#define HAVE_INHERITED_NONBLOCK 1
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user