nginx-0.0.1-2003-11-09-23:03:38 import; separate building

This commit is contained in:
Igor Sysoev 2003-11-09 20:03:38 +00:00
parent e8732b06b9
commit 74e95c224a
35 changed files with 1661 additions and 571 deletions

View File

@ -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;

View File

@ -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

View File

@ -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
};

View File

@ -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';
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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;

View File

@ -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,

View 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;
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View 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);

View File

@ -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 "

View File

@ -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;

View File

@ -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);
}

View File

@ -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) },

View 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;
}

View 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_ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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 */

View File

@ -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)
{

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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