mirror of
https://github.com/nginx/nginx.git
synced 2025-06-07 01:12:40 +08:00
a prelimiary proxy cache support
This commit is contained in:
parent
1af7090b50
commit
52859f2f13
12
auto/modules
12
auto/modules
@ -65,6 +65,13 @@ if [ $HTTP != YES ]; then
|
||||
fi
|
||||
|
||||
|
||||
if [ $HTTP_CACHE = YES ]; then
|
||||
USE_MD5=YES
|
||||
have=NGX_HTTP_CACHE . auto/have
|
||||
HTTP_SRCS="$HTTP_SRCS $HTTP_FILE_CACHE_SRCS"
|
||||
fi
|
||||
|
||||
|
||||
if [ $HTTP_SSI = YES ]; then
|
||||
HTTP_POSTPONE=YES
|
||||
fi
|
||||
@ -305,11 +312,6 @@ if [ $HTTP_UPSTREAM_IP_HASH = YES ]; then
|
||||
HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_IP_HASH_SRCS"
|
||||
fi
|
||||
|
||||
# STUB
|
||||
#USE_MD5=YES
|
||||
#HTTP_SRCS="$HTTP_SRCS $HTTP_CACHE_SRCS"
|
||||
#HTTP_SRCS="$HTTP_SRCS $HTTP_FILE_CACHE_SRCS"
|
||||
|
||||
if [ $HTTP_STUB_STATUS = YES ]; then
|
||||
have=NGX_STAT_STUB . auto/have
|
||||
HTTP_MODULES="$HTTP_MODULES ngx_http_stub_status_module"
|
||||
|
@ -52,6 +52,7 @@ NGX_HTTP_CLIENT_TEMP_PATH=
|
||||
NGX_HTTP_PROXY_TEMP_PATH=
|
||||
NGX_HTTP_FASTCGI_TEMP_PATH=
|
||||
|
||||
HTTP_CACHE=YES
|
||||
HTTP_CHARSET=YES
|
||||
HTTP_GZIP=YES
|
||||
HTTP_SSL=NO
|
||||
@ -165,6 +166,8 @@ do
|
||||
--with-ipv6) NGX_IPV6=YES ;;
|
||||
|
||||
--without-http) HTTP=NO ;;
|
||||
--without-http-cache) HTTP_CACHE=NO ;;
|
||||
|
||||
--http-log-path=*) NGX_HTTP_LOG_PATH="$value" ;;
|
||||
--http-client-body-temp-path=*) NGX_HTTP_CLIENT_TEMP_PATH="$value" ;;
|
||||
--http-proxy-temp-path=*) NGX_HTTP_PROXY_TEMP_PATH="$value" ;;
|
||||
@ -337,6 +340,7 @@ cat << END
|
||||
files
|
||||
|
||||
--without-http disable HTTP server
|
||||
--without-http-cache disable HTTP cache
|
||||
|
||||
--with-mail enable POP3/IMAP4/SMTP proxy module
|
||||
--with-mail_ssl_module enable ngx_mail_ssl_module
|
||||
|
@ -33,8 +33,7 @@ CORE_DEPS="src/core/nginx.h \
|
||||
src/core/ngx_cycle.h \
|
||||
src/core/ngx_conf_file.h \
|
||||
src/core/ngx_resolver.h \
|
||||
src/core/ngx_open_file_cache.h \
|
||||
src/core/ngx_garbage_collector.h"
|
||||
src/core/ngx_open_file_cache.h"
|
||||
|
||||
|
||||
CORE_SRCS="src/core/nginx.c \
|
||||
@ -62,8 +61,7 @@ CORE_SRCS="src/core/nginx.c \
|
||||
src/core/ngx_cpuinfo.c \
|
||||
src/core/ngx_conf_file.c \
|
||||
src/core/ngx_resolver.c \
|
||||
src/core/ngx_open_file_cache.c \
|
||||
src/core/ngx_garbage_collector.c"
|
||||
src/core/ngx_open_file_cache.c"
|
||||
|
||||
|
||||
REGEX_DEPS=src/core/ngx_regex.h
|
||||
@ -254,8 +252,6 @@ HTTP_MODULES="ngx_http_module \
|
||||
ngx_http_log_module \
|
||||
ngx_http_upstream_module"
|
||||
|
||||
HTTP_CACHE_MODULE=ngx_http_cache_module
|
||||
|
||||
HTTP_WRITE_FILTER_MODULE="ngx_http_write_filter_module"
|
||||
HTTP_HEADER_FILTER_MODULE="ngx_http_header_filter_module"
|
||||
|
||||
@ -313,7 +309,6 @@ HTTP_SRCS="$HTTP_SRCS src/http/ngx_http_busy_lock.c"
|
||||
|
||||
HTTP_POSTPONE_FILTER_SRCS=src/http/ngx_http_postpone_filter_module.c
|
||||
|
||||
HTTP_CACHE_SRCS=src/http/ngx_http_cache.c
|
||||
HTTP_FILE_CACHE_SRCS=src/http/ngx_http_file_cache.c
|
||||
|
||||
|
||||
|
@ -264,7 +264,7 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
|
||||
path->len = 0;
|
||||
path->cleaner = (ngx_gc_handler_pt) cmd->post;
|
||||
path->cleaner = (ngx_path_cleaner_pt) cmd->post;
|
||||
path->conf_file = cf->conf_file->file.name.data;
|
||||
path->line = cf->conf_file->line;
|
||||
|
||||
@ -292,6 +292,49 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path, ngx_path_t *prev,
|
||||
ngx_path_init_t *init)
|
||||
{
|
||||
if (*path) {
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
*path = prev;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
*path = ngx_palloc(cf->pool, sizeof(ngx_path_t));
|
||||
if (*path == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
(*path)->name = init->name;
|
||||
|
||||
if (ngx_conf_full_name(cf->cycle, &(*path)->name, 0) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
(*path)->level[0] = init->level[0];
|
||||
(*path)->level[1] = init->level[1];
|
||||
(*path)->level[2] = init->level[2];
|
||||
|
||||
(*path)->len = init->level[0] + (init->level[0] ? 1 : 0)
|
||||
+ init->level[1] + (init->level[1] ? 1 : 0)
|
||||
+ init->level[2] + (init->level[2] ? 1 : 0);
|
||||
|
||||
(*path)->cleaner = NULL;
|
||||
(*path)->conf_file = NULL;
|
||||
|
||||
if (ngx_add_path(cf, path) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
|
@ -11,65 +11,73 @@
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
typedef struct ngx_path_s ngx_path_t;
|
||||
|
||||
#include <ngx_garbage_collector.h>
|
||||
|
||||
|
||||
struct ngx_file_s {
|
||||
ngx_fd_t fd;
|
||||
ngx_str_t name;
|
||||
ngx_file_info_t info;
|
||||
ngx_fd_t fd;
|
||||
ngx_str_t name;
|
||||
ngx_file_info_t info;
|
||||
|
||||
off_t offset;
|
||||
off_t sys_offset;
|
||||
off_t offset;
|
||||
off_t sys_offset;
|
||||
|
||||
ngx_log_t *log;
|
||||
ngx_log_t *log;
|
||||
|
||||
unsigned valid_info:1;
|
||||
unsigned directio:1;
|
||||
unsigned valid_info:1;
|
||||
unsigned directio:1;
|
||||
};
|
||||
|
||||
#define NGX_MAX_PATH_LEVEL 3
|
||||
|
||||
struct ngx_path_s {
|
||||
ngx_str_t name;
|
||||
size_t len;
|
||||
size_t level[3];
|
||||
ngx_gc_handler_pt cleaner;
|
||||
|
||||
u_char *conf_file;
|
||||
ngx_uint_t line;
|
||||
};
|
||||
typedef time_t (*ngx_path_cleaner_pt) (void *data);
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_file_t file;
|
||||
off_t offset;
|
||||
ngx_path_t *path;
|
||||
ngx_pool_t *pool;
|
||||
char *warn;
|
||||
ngx_str_t name;
|
||||
size_t len;
|
||||
size_t level[3];
|
||||
|
||||
ngx_uint_t access;
|
||||
ngx_path_cleaner_pt cleaner;
|
||||
void *data;
|
||||
|
||||
unsigned log_level:8;
|
||||
unsigned persistent:1;
|
||||
unsigned clean:1;
|
||||
u_char *conf_file;
|
||||
ngx_uint_t line;
|
||||
} ngx_path_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name;
|
||||
size_t level[3];
|
||||
} ngx_path_init_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_file_t file;
|
||||
off_t offset;
|
||||
ngx_path_t *path;
|
||||
ngx_pool_t *pool;
|
||||
char *warn;
|
||||
|
||||
ngx_uint_t access;
|
||||
|
||||
unsigned log_level:8;
|
||||
unsigned persistent:1;
|
||||
unsigned clean:1;
|
||||
} ngx_temp_file_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_uint_t access;
|
||||
ngx_uint_t path_access;
|
||||
time_t time;
|
||||
ngx_fd_t fd;
|
||||
ngx_err_t rename_error;
|
||||
ngx_uint_t access;
|
||||
ngx_uint_t path_access;
|
||||
time_t time;
|
||||
ngx_fd_t fd;
|
||||
ngx_err_t rename_error;
|
||||
|
||||
unsigned create_path:1;
|
||||
unsigned delete_file:1;
|
||||
unsigned log_rename_error:1;
|
||||
unsigned create_path:1;
|
||||
unsigned delete_file:1;
|
||||
unsigned log_rename_error:1;
|
||||
|
||||
ngx_log_t *log;
|
||||
ngx_log_t *log;
|
||||
} ngx_ext_rename_file_t;
|
||||
|
||||
|
||||
@ -113,40 +121,9 @@ void ngx_init_temp_number(void);
|
||||
ngx_atomic_uint_t ngx_next_temp_number(ngx_uint_t collision);
|
||||
|
||||
char *ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
char *ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path,
|
||||
ngx_path_t *prev, ngx_path_init_t *init);
|
||||
char *ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
|
||||
|
||||
#define ngx_conf_merge_path_value(curr, prev, path, l1, l2, l3, clean, cf) \
|
||||
if (curr == NULL) { \
|
||||
if (prev == NULL) { \
|
||||
curr = ngx_palloc(cf->pool, sizeof(ngx_path_t)); \
|
||||
if (curr == NULL) { \
|
||||
return NGX_CONF_ERROR; \
|
||||
} \
|
||||
\
|
||||
curr->name.len = sizeof(path) - 1; \
|
||||
curr->name.data = (u_char *) path; \
|
||||
\
|
||||
if (ngx_conf_full_name(cf->cycle, &curr->name, 0) == NGX_ERROR) { \
|
||||
return NGX_CONF_ERROR; \
|
||||
} \
|
||||
\
|
||||
curr->level[0] = l1; \
|
||||
curr->level[1] = l2; \
|
||||
curr->level[2] = l3; \
|
||||
curr->len = l1 + l2 + l3 + (l1 ? 1:0) + (l2 ? 1:0) + (l3 ? 1:0); \
|
||||
curr->cleaner = clean; \
|
||||
curr->conf_file = NULL; \
|
||||
\
|
||||
if (ngx_add_path(cf, &curr) == NGX_ERROR) { \
|
||||
return NGX_CONF_ERROR; \
|
||||
} \
|
||||
\
|
||||
} else { \
|
||||
curr = prev; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* _NGX_FILE_H_INCLUDED_ */
|
||||
|
@ -1,217 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
|
||||
|
||||
ngx_int_t ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, ngx_int_t level)
|
||||
{
|
||||
int rc;
|
||||
u_char *last;
|
||||
size_t len;
|
||||
ngx_err_t err;
|
||||
ngx_str_t fname, buf;
|
||||
ngx_dir_t dir;
|
||||
|
||||
buf.len = 0;
|
||||
#if (NGX_SUPPRESS_WARN)
|
||||
buf.data = NULL;
|
||||
fname.data = NULL;
|
||||
#endif
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0,
|
||||
"gc dir \"%s\":%d", dname->data, dname->len);
|
||||
|
||||
if (ngx_open_dir(dname, &dir) == NGX_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
ngx_open_dir_n " \"%s\" failed", dname->data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
for ( ;; ) {
|
||||
ngx_set_errno(0);
|
||||
if (ngx_read_dir(&dir) == NGX_ERROR) {
|
||||
err = ngx_errno;
|
||||
|
||||
if (err != NGX_ENOMOREFILES) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, err,
|
||||
ngx_read_dir_n " \"%s\" failed", dname->data);
|
||||
rc = NGX_ERROR;
|
||||
|
||||
} else {
|
||||
rc = NGX_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
len = ngx_de_namelen(&dir);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->log, 0,
|
||||
"gc name \"%s\":%d", ngx_de_name(&dir), len);
|
||||
|
||||
if (len == 1 && ngx_de_name(&dir)[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len == 2
|
||||
&& ngx_de_name(&dir)[0] == '.'
|
||||
&& ngx_de_name(&dir)[1] == '.')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
fname.len = dname->len + 1+ len;
|
||||
|
||||
if (fname.len + NGX_DIR_MASK_LEN > buf.len) {
|
||||
|
||||
if (buf.len) {
|
||||
ngx_free(buf.data);
|
||||
}
|
||||
|
||||
buf.len = dname->len + 1 + len + NGX_DIR_MASK_LEN;
|
||||
|
||||
buf.data = ngx_alloc(buf.len + 1, ctx->log);
|
||||
if (buf.data == NULL) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
last = ngx_cpymem(buf.data, dname->data, dname->len);
|
||||
*last++ = '/';
|
||||
ngx_memcpy(last, ngx_de_name(&dir), len + 1);
|
||||
fname.data = buf.data;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
|
||||
"gc path: \"%s\"", fname.data);
|
||||
|
||||
if (!dir.valid_info) {
|
||||
if (ngx_de_info(fname.data, &dir) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
ngx_de_info_n " \"%s\" failed", fname.data);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_de_is_dir(&dir)) {
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
|
||||
"gc enter dir \"%s\"", fname.data);
|
||||
|
||||
if (level == -1
|
||||
/* there can not be directory on the last level */
|
||||
|| level == NGX_MAX_PATH_LEVEL
|
||||
/* an directory from the old path hierarchy */
|
||||
|| len != ctx->path->level[level])
|
||||
{
|
||||
if (ngx_collect_garbage(ctx, &fname, -1) == NGX_ABORT) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
fname.data[fname.len] = '\0';
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0,
|
||||
"delete old hierachy directory \"%s\"",
|
||||
fname.data);
|
||||
|
||||
if (ngx_delete_dir(fname.data) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
ngx_delete_dir_n " \"%s\" failed",
|
||||
fname.data);
|
||||
} else {
|
||||
ctx->deleted++;
|
||||
ctx->freed += ngx_de_size(&dir);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_collect_garbage(ctx, &fname, level + 1) == NGX_ABORT) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
} else if (ngx_de_is_file(&dir)) {
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
|
||||
"gc file \"%s\"", fname.data);
|
||||
|
||||
if (level == -1
|
||||
|| (level < NGX_MAX_PATH_LEVEL && ctx->path->level[level] != 0))
|
||||
{
|
||||
if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
ngx_delete_file_n " \"%s\" failed",
|
||||
fname.data);
|
||||
} else {
|
||||
ctx->deleted++;
|
||||
ctx->freed += ngx_de_size(&dir);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctx->handler(ctx, &fname, &dir) == NGX_ABORT) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
} else {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
"the file \"%s\" has unknown type, deleting",
|
||||
fname.data);
|
||||
|
||||
if (ngx_delete_file(fname.data) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
ngx_delete_file_n " \"%s\" failed", fname.data);
|
||||
} else {
|
||||
ctx->deleted++;
|
||||
ctx->freed += ngx_de_size(&dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buf.len) {
|
||||
ngx_free(buf.data);
|
||||
}
|
||||
|
||||
if (ngx_close_dir(&dir) == NGX_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
ngx_close_dir_n " \"%s\" failed", fname.data);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name,
|
||||
ngx_dir_t *dir)
|
||||
{
|
||||
/*
|
||||
* We use mtime only and do not use atime because:
|
||||
* on NTFS access time has a resolution of 1 hour,
|
||||
* on NT FAT access time has a resolution of 1 day,
|
||||
* Unices have the mount option "noatime".
|
||||
*/
|
||||
|
||||
if (ngx_time() - ngx_de_mtime(dir) < 3600) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, ctx->log, 0,
|
||||
"delete the stale temporary file \"%s\"", name->data);
|
||||
|
||||
if (ngx_delete_file(name->data) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, ctx->log, ngx_errno,
|
||||
ngx_delete_file_n " \"%s\" failed", name->data);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ctx->deleted++;
|
||||
ctx->freed += ngx_de_size(dir);
|
||||
|
||||
return NGX_OK;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _NGX_GARBAGE_COLLECTOR_H_INCLUDED_
|
||||
#define _NGX_GARBAGE_COLLECTOR_H_INCLUDED_
|
||||
|
||||
|
||||
typedef struct ngx_gc_s ngx_gc_t;
|
||||
|
||||
typedef ngx_int_t (*ngx_gc_handler_pt) (ngx_gc_t *ctx, ngx_str_t *name,
|
||||
ngx_dir_t *dir);
|
||||
|
||||
|
||||
struct ngx_gc_s {
|
||||
ngx_path_t *path;
|
||||
u_int deleted;
|
||||
off_t freed;
|
||||
ngx_gc_handler_pt handler;
|
||||
ngx_log_t *log;
|
||||
};
|
||||
|
||||
|
||||
ngx_int_t ngx_collect_garbage(ngx_gc_t *ctx, ngx_str_t *dname, ngx_int_t level);
|
||||
ngx_int_t ngx_garbage_collector_temp_handler(ngx_gc_t *ctx, ngx_str_t *name,
|
||||
ngx_dir_t *dir);
|
||||
|
||||
|
||||
#endif /* _NGX_GARBAGE_COLLECTOR_H_INCLUDED_ */
|
@ -325,6 +325,27 @@ ngx_pool_cleanup_add(ngx_pool_t *p, size_t size)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd)
|
||||
{
|
||||
ngx_pool_cleanup_t *c;
|
||||
ngx_pool_cleanup_file_t *cf;
|
||||
|
||||
for (c = p->cleanup; c; c = c->next) {
|
||||
if (c->handler == ngx_pool_cleanup_file) {
|
||||
|
||||
cf = c->data;
|
||||
|
||||
if (cf->fd == fd) {
|
||||
c->handler(cf);
|
||||
c->handler = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ngx_pool_cleanup_file(void *data)
|
||||
{
|
||||
|
@ -82,6 +82,7 @@ ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
|
||||
|
||||
|
||||
ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);
|
||||
void ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd);
|
||||
void ngx_pool_cleanup_file(void *data);
|
||||
void ngx_pool_delete_file(void *data);
|
||||
|
||||
|
@ -423,7 +423,7 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
|
||||
size_t bsize;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t flush, prev_last_shadow;
|
||||
ngx_chain_t *out, **ll, *cl;
|
||||
ngx_chain_t *out, **ll, *cl, file;
|
||||
ngx_connection_t *downstream;
|
||||
|
||||
downstream = p->downstream;
|
||||
@ -488,6 +488,18 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
|
||||
p->in = NULL;
|
||||
}
|
||||
|
||||
if (p->cacheable && p->buf_to_file) {
|
||||
|
||||
file.buf = p->buf_to_file;
|
||||
file.next = NULL;
|
||||
|
||||
if (ngx_write_chain_to_temp_file(p->temp_file, &file)
|
||||
== NGX_ERROR)
|
||||
{
|
||||
return NGX_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
|
||||
"pipe write downstream done");
|
||||
|
||||
|
@ -288,7 +288,7 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
|
||||
ngx_conf_set_path_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_path),
|
||||
(void *) ngx_garbage_collector_temp_handler },
|
||||
NULL },
|
||||
|
||||
{ ngx_string("fastcgi_max_temp_file_size"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
@ -436,6 +436,11 @@ static ngx_str_t ngx_http_fastcgi_hide_headers[] = {
|
||||
};
|
||||
|
||||
|
||||
static ngx_path_init_t ngx_http_fastcgi_temp_path = {
|
||||
ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
|
||||
};
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_fastcgi_handler(ngx_http_request_t *r)
|
||||
{
|
||||
@ -1923,10 +1928,13 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|NGX_HTTP_UPSTREAM_FT_OFF;
|
||||
}
|
||||
|
||||
ngx_conf_merge_path_value(conf->upstream.temp_path,
|
||||
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
||||
prev->upstream.temp_path,
|
||||
NGX_HTTP_FASTCGI_TEMP_PATH, 1, 2, 0,
|
||||
ngx_garbage_collector_temp_handler, cf);
|
||||
&ngx_http_fastcgi_temp_path)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.pass_request_headers,
|
||||
prev->upstream.pass_request_headers, 1);
|
||||
|
@ -83,6 +83,7 @@ ngx_int_t ngx_http_not_modified_header_filter(ngx_http_request_t *r)
|
||||
}
|
||||
|
||||
r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
|
||||
r->headers_out.status_line.len = 0;
|
||||
r->headers_out.content_type.len = 0;
|
||||
ngx_http_clear_content_length(r);
|
||||
ngx_http_clear_accept_ranges(r);
|
||||
|
@ -32,6 +32,7 @@ struct ngx_http_proxy_redirect_s {
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t key_start;
|
||||
ngx_str_t schema;
|
||||
ngx_str_t host_header;
|
||||
ngx_str_t port;
|
||||
@ -89,6 +90,9 @@ typedef struct {
|
||||
|
||||
static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
|
||||
ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
|
||||
#if (NGX_HTTP_CACHE)
|
||||
static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r);
|
||||
#endif
|
||||
static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
|
||||
static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
|
||||
@ -116,6 +120,8 @@ static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
|
||||
static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
|
||||
static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
|
||||
void *parent, void *child);
|
||||
static ngx_int_t ngx_http_proxy_merge_headers(ngx_conf_t *cf,
|
||||
ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_loc_conf_t *prev);
|
||||
|
||||
static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
@ -123,6 +129,10 @@ static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
#if (NGX_HTTP_CACHE)
|
||||
static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
#endif
|
||||
|
||||
static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
|
||||
|
||||
@ -135,8 +145,7 @@ static char *ngx_http_proxy_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
|
||||
static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
|
||||
ngx_http_proxy_loc_conf_t *plcf);
|
||||
#endif
|
||||
static ngx_int_t ngx_http_proxy_set_vars(ngx_pool_t *pool, ngx_url_t *u,
|
||||
ngx_http_proxy_vars_t *v);
|
||||
static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v);
|
||||
|
||||
|
||||
static ngx_conf_post_t ngx_http_proxy_lowat_post =
|
||||
@ -157,6 +166,9 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_http_proxy_module;
|
||||
|
||||
|
||||
static ngx_command_t ngx_http_proxy_commands[] = {
|
||||
|
||||
{ ngx_string("proxy_pass"),
|
||||
@ -306,12 +318,51 @@ static ngx_command_t ngx_http_proxy_commands[] = {
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf),
|
||||
NULL },
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
{ ngx_string("proxy_cache"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_http_proxy_cache,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_cache_path"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
|
||||
ngx_http_file_cache_set_slot,
|
||||
0,
|
||||
0,
|
||||
&ngx_http_proxy_module },
|
||||
|
||||
{ ngx_string("proxy_cache_valid"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
|
||||
ngx_http_file_cache_valid_set_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_valid),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_cache_min_uses"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
ngx_conf_set_num_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_cache_use_stale"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
|
||||
ngx_conf_set_bitmask_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_use_stale),
|
||||
&ngx_http_proxy_next_upstream_masks },
|
||||
|
||||
#endif
|
||||
|
||||
{ ngx_string("proxy_temp_path"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
|
||||
ngx_conf_set_path_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
|
||||
(void *) ngx_garbage_collector_temp_handler },
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_max_temp_file_size"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||
@ -455,6 +506,11 @@ static ngx_http_variable_t ngx_http_proxy_vars[] = {
|
||||
};
|
||||
|
||||
|
||||
static ngx_path_init_t ngx_http_proxy_temp_path = {
|
||||
ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 }
|
||||
};
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
{
|
||||
@ -502,6 +558,9 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
|
||||
|
||||
u->conf = &plcf->upstream;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
u->create_key = ngx_http_proxy_create_key;
|
||||
#endif
|
||||
u->create_request = ngx_http_proxy_create_request;
|
||||
u->reinit_request = ngx_http_proxy_reinit_request;
|
||||
u->process_header = ngx_http_proxy_process_status_line;
|
||||
@ -537,11 +596,12 @@ static ngx_int_t
|
||||
ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
|
||||
ngx_http_proxy_loc_conf_t *plcf)
|
||||
{
|
||||
u_char *p;
|
||||
size_t add;
|
||||
u_short port;
|
||||
ngx_str_t proxy;
|
||||
ngx_url_t u;
|
||||
u_char *p;
|
||||
size_t add;
|
||||
u_short port;
|
||||
ngx_str_t proxy;
|
||||
ngx_url_t url;
|
||||
ngx_http_upstream_t *u;
|
||||
|
||||
if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0,
|
||||
plcf->proxy_values->elts)
|
||||
@ -571,70 +631,162 @@ ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->upstream->schema.len = add;
|
||||
r->upstream->schema.data = proxy.data;
|
||||
u = r->upstream;
|
||||
|
||||
ngx_memzero(&u, sizeof(ngx_url_t));
|
||||
u->schema.len = add;
|
||||
u->schema.data = proxy.data;
|
||||
|
||||
u.url.len = proxy.len - add;
|
||||
u.url.data = proxy.data + add;
|
||||
u.default_port = port;
|
||||
u.uri_part = 1;
|
||||
u.no_resolve = 1;
|
||||
ngx_memzero(&url, sizeof(ngx_url_t));
|
||||
|
||||
if (ngx_parse_url(r->pool, &u) != NGX_OK) {
|
||||
if (u.err) {
|
||||
url.url.len = proxy.len - add;
|
||||
url.url.data = proxy.data + add;
|
||||
url.default_port = port;
|
||||
url.uri_part = 1;
|
||||
url.no_resolve = 1;
|
||||
|
||||
if (ngx_parse_url(r->pool, &url) != NGX_OK) {
|
||||
if (url.err) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"%s in upstream \"%V\"", u.err, &u.url);
|
||||
"%s in upstream \"%V\"", url.err, &url.url);
|
||||
}
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (u.uri.len && u.uri.data[0] == '?') {
|
||||
p = ngx_pnalloc(r->pool, u.uri.len + 1);
|
||||
if (url.uri.len && url.uri.data[0] == '?') {
|
||||
p = ngx_pnalloc(r->pool, url.uri.len + 1);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*p++ = '/';
|
||||
ngx_memcpy(p, u.uri.data, u.uri.len);
|
||||
ngx_memcpy(p, url.uri.data, url.uri.len);
|
||||
|
||||
u.uri.len++;
|
||||
u.uri.data = p - 1;
|
||||
url.uri.len++;
|
||||
url.uri.data = p - 1;
|
||||
}
|
||||
|
||||
if (ngx_http_proxy_set_vars(r->pool, &u, &ctx->vars) != NGX_OK) {
|
||||
ctx->vars.key_start = u->schema;
|
||||
|
||||
ngx_http_proxy_set_vars(&url, &ctx->vars);
|
||||
|
||||
u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
|
||||
if (u->resolved == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->upstream->resolved = ngx_pcalloc(r->pool,
|
||||
sizeof(ngx_http_upstream_resolved_t));
|
||||
if (r->upstream->resolved == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (u.addrs && u.addrs[0].sockaddr) {
|
||||
r->upstream->resolved->sockaddr = u.addrs[0].sockaddr;
|
||||
r->upstream->resolved->socklen = u.addrs[0].socklen;
|
||||
r->upstream->resolved->naddrs = 1;
|
||||
r->upstream->resolved->host = u.addrs[0].name;
|
||||
if (url.addrs && url.addrs[0].sockaddr) {
|
||||
u->resolved->sockaddr = url.addrs[0].sockaddr;
|
||||
u->resolved->socklen = url.addrs[0].socklen;
|
||||
u->resolved->naddrs = 1;
|
||||
u->resolved->host = url.addrs[0].name;
|
||||
|
||||
} else {
|
||||
r->upstream->resolved->host = u.host;
|
||||
r->upstream->resolved->port = (in_port_t) (u.no_port ? u.default_port:
|
||||
u.port);
|
||||
r->upstream->resolved->no_port = u.no_port;
|
||||
u->resolved->host = url.host;
|
||||
u->resolved->port = (in_port_t) (url.no_port ? port : url.port);
|
||||
u->resolved->no_port = url.no_port;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_create_key(ngx_http_request_t *r)
|
||||
{
|
||||
size_t len, loc_len;
|
||||
u_char *p;
|
||||
uintptr_t escape;
|
||||
ngx_str_t *key;
|
||||
ngx_http_upstream_t *u;
|
||||
ngx_http_proxy_ctx_t *ctx;
|
||||
ngx_http_proxy_loc_conf_t *plcf;
|
||||
|
||||
u = r->upstream;
|
||||
|
||||
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
||||
|
||||
key = ngx_array_push(&r->cache->keys);
|
||||
if (key == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*key = ctx->vars.key_start;
|
||||
|
||||
key = ngx_array_push(&r->cache->keys);
|
||||
if (key == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (plcf->proxy_lengths) {
|
||||
|
||||
*key = ctx->vars.uri;
|
||||
u->uri = ctx->vars.uri;
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
} else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
|
||||
{
|
||||
*key = r->unparsed_uri;
|
||||
u->uri = r->unparsed_uri;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
|
||||
|
||||
if (r->quoted_uri || r->internal) {
|
||||
escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
|
||||
r->uri.len - loc_len, NGX_ESCAPE_URI);
|
||||
} else {
|
||||
escape = 0;
|
||||
}
|
||||
|
||||
len = ctx->vars.uri.len + r->uri.len - loc_len + escape
|
||||
+ sizeof("?") - 1 + r->args.len;
|
||||
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
key->data = p;
|
||||
|
||||
if (r->valid_location) {
|
||||
p = ngx_copy(p, ctx->vars.uri.data, ctx->vars.uri.len);
|
||||
}
|
||||
|
||||
if (escape) {
|
||||
ngx_escape_uri(p, r->uri.data + loc_len,
|
||||
r->uri.len - loc_len, NGX_ESCAPE_URI);
|
||||
p += r->uri.len - loc_len + escape;
|
||||
|
||||
} else {
|
||||
p = ngx_copy(p, r->uri.data + loc_len, r->uri.len - loc_len);
|
||||
}
|
||||
|
||||
if (r->args.len > 0) {
|
||||
*p++ = '?';
|
||||
p = ngx_copy(p, r->args.data, r->args.len);
|
||||
}
|
||||
|
||||
key->len = p - key->data;
|
||||
u->uri = *key;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
{
|
||||
size_t len, loc_len, body_len;
|
||||
size_t len, uri_len, loc_len, body_len;
|
||||
uintptr_t escape;
|
||||
ngx_buf_t *b;
|
||||
ngx_str_t method;
|
||||
@ -675,12 +827,12 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
||||
|
||||
if (plcf->proxy_lengths) {
|
||||
len += ctx->vars.uri.len;
|
||||
uri_len = ctx->vars.uri.len;
|
||||
|
||||
} else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
|
||||
{
|
||||
unparsed_uri = 1;
|
||||
len += r->unparsed_uri.len;
|
||||
uri_len = r->unparsed_uri.len;
|
||||
|
||||
} else {
|
||||
loc_len = (r->valid_location && ctx->vars.uri.len) ?
|
||||
@ -691,10 +843,18 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
|
||||
r->uri.len - loc_len, NGX_ESCAPE_URI);
|
||||
}
|
||||
|
||||
len += ctx->vars.uri.len + r->uri.len - loc_len + escape
|
||||
+ sizeof("?") - 1 + r->args.len;
|
||||
uri_len = ctx->vars.uri.len + r->uri.len - loc_len + escape
|
||||
+ sizeof("?") - 1 + r->args.len;
|
||||
}
|
||||
|
||||
if (uri_len == 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"zero length URI to proxy");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
len += uri_len;
|
||||
|
||||
ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes);
|
||||
|
||||
if (plcf->body_set_len) {
|
||||
@ -980,6 +1140,17 @@ ngx_http_proxy_process_status_line(ngx_http_request_t *r)
|
||||
u = r->upstream;
|
||||
|
||||
if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (r->cache) {
|
||||
r->http_version = NGX_HTTP_VERSION_9;
|
||||
u->headers_in.status_n = NGX_HTTP_OK;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"upstream sent no valid HTTP/1.0 header");
|
||||
|
||||
@ -996,8 +1167,11 @@ ngx_http_proxy_process_status_line(ngx_http_request_t *r)
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (u->state) {
|
||||
u->state->status = ctx->status;
|
||||
}
|
||||
|
||||
u->headers_in.status_n = ctx->status;
|
||||
u->state->status = ctx->status;
|
||||
|
||||
u->headers_in.status_line.len = ctx->status_end - ctx->status_start;
|
||||
u->headers_in.status_line.data = ngx_pnalloc(r->pool,
|
||||
@ -1638,6 +1812,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
||||
*
|
||||
* conf->upstream.bufs.num = 0;
|
||||
* conf->upstream.next_upstream = 0;
|
||||
* conf->upstream.use_stale_cache = 0;
|
||||
* conf->upstream.temp_path = NULL;
|
||||
* conf->upstream.hide_headers_hash = { NULL, 0 };
|
||||
* conf->upstream.uri = { 0, NULL };
|
||||
@ -1675,6 +1850,12 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
||||
conf->upstream.pass_request_headers = NGX_CONF_UNSET;
|
||||
conf->upstream.pass_request_body = NGX_CONF_UNSET;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
conf->upstream.cache = NGX_CONF_UNSET_PTR;
|
||||
conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
|
||||
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
|
||||
#endif
|
||||
|
||||
conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
|
||||
conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
|
||||
|
||||
@ -1702,16 +1883,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_http_proxy_loc_conf_t *prev = parent;
|
||||
ngx_http_proxy_loc_conf_t *conf = child;
|
||||
|
||||
u_char *p;
|
||||
size_t size;
|
||||
uintptr_t *code;
|
||||
ngx_uint_t i;
|
||||
ngx_keyval_t *src, *s, *h;
|
||||
ngx_hash_key_t *hk;
|
||||
ngx_hash_init_t hash;
|
||||
ngx_http_proxy_redirect_t *pr;
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_http_script_copy_code_t *copy;
|
||||
size_t size;
|
||||
ngx_keyval_t *s;
|
||||
ngx_hash_init_t hash;
|
||||
ngx_http_proxy_redirect_t *pr;
|
||||
ngx_http_script_compile_t sc;
|
||||
|
||||
if (conf->upstream.store != 0) {
|
||||
ngx_conf_merge_value(conf->upstream.store,
|
||||
@ -1850,10 +2026,53 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|NGX_HTTP_UPSTREAM_FT_OFF;
|
||||
}
|
||||
|
||||
ngx_conf_merge_path_value(conf->upstream.temp_path,
|
||||
if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
|
||||
prev->upstream.temp_path,
|
||||
NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0,
|
||||
ngx_garbage_collector_temp_handler, cf);
|
||||
&ngx_http_proxy_temp_path)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->upstream.cache,
|
||||
prev->upstream.cache, NULL);
|
||||
|
||||
if (conf->upstream.cache && conf->upstream.cache->data == NULL) {
|
||||
ngx_shm_zone_t *shm_zone;
|
||||
|
||||
shm_zone = conf->upstream.cache;
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"\"proxy_cache\" zone \"%V\" is unknown",
|
||||
&shm_zone->name);
|
||||
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
|
||||
prev->upstream.cache_min_uses, 1);
|
||||
|
||||
ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
|
||||
prev->upstream.cache_use_stale,
|
||||
(NGX_CONF_BITMASK_SET
|
||||
|NGX_HTTP_UPSTREAM_FT_OFF));
|
||||
|
||||
if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
|
||||
conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
|
||||
|NGX_HTTP_UPSTREAM_FT_OFF;
|
||||
}
|
||||
|
||||
ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
|
||||
prev->upstream.cache_valid, NULL);
|
||||
|
||||
if (conf->upstream.cache_valid == NULL) {
|
||||
conf->upstream.cache = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (conf->method.len == 0) {
|
||||
conf->method = prev->method;
|
||||
@ -1984,6 +2203,27 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
s->value.data = (u_char *) "$proxy_internal_body_length";
|
||||
}
|
||||
|
||||
if (ngx_http_proxy_merge_headers(cf, conf, prev) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_merge_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
|
||||
ngx_http_proxy_loc_conf_t *prev)
|
||||
{
|
||||
u_char *p;
|
||||
size_t size;
|
||||
uintptr_t *code;
|
||||
ngx_uint_t i;
|
||||
ngx_keyval_t *src, *s, *h;
|
||||
ngx_hash_key_t *hk;
|
||||
ngx_hash_init_t hash;
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_http_script_copy_code_t *copy;
|
||||
|
||||
if (conf->headers_source == NULL) {
|
||||
conf->flushes = prev->flushes;
|
||||
@ -1994,31 +2234,31 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
}
|
||||
|
||||
if (conf->headers_set_hash.buckets) {
|
||||
return NGX_CONF_OK;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
conf->headers_names = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
|
||||
if (conf->headers_names == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (conf->headers_source == NULL) {
|
||||
conf->headers_source = ngx_array_create(cf->pool, 4,
|
||||
sizeof(ngx_keyval_t));
|
||||
if (conf->headers_source == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
conf->headers_set_len = ngx_array_create(cf->pool, 64, 1);
|
||||
if (conf->headers_set_len == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
conf->headers_set = ngx_array_create(cf->pool, 512, 1);
|
||||
if (conf->headers_set == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@ -2034,7 +2274,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
s = ngx_array_push(conf->headers_source);
|
||||
if (s == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*s = *h;
|
||||
@ -2052,7 +2292,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
hk = ngx_array_push(conf->headers_names);
|
||||
if (hk == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
hk->key = src[i].key;
|
||||
@ -2067,7 +2307,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
copy = ngx_array_push_n(conf->headers_set_len,
|
||||
sizeof(ngx_http_script_copy_code_t));
|
||||
if (copy == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
copy->code = (ngx_http_script_code_pt)
|
||||
@ -2084,7 +2324,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
copy = ngx_array_push_n(conf->headers_set, size);
|
||||
if (copy == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
copy->code = ngx_http_script_copy_code;
|
||||
@ -2102,7 +2342,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
copy = ngx_array_push_n(conf->headers_set_len,
|
||||
sizeof(ngx_http_script_copy_code_t));
|
||||
if (copy == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
copy->code = (ngx_http_script_code_pt)
|
||||
@ -2116,7 +2356,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
copy = ngx_array_push_n(conf->headers_set, size);
|
||||
if (copy == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
copy->code = ngx_http_script_copy_code;
|
||||
@ -2136,14 +2376,14 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
sc.values = &conf->headers_set;
|
||||
|
||||
if (ngx_http_script_compile(&sc) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
copy = ngx_array_push_n(conf->headers_set_len,
|
||||
sizeof(ngx_http_script_copy_code_t));
|
||||
if (copy == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
copy->code = (ngx_http_script_code_pt)
|
||||
@ -2157,7 +2397,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
copy = ngx_array_push_n(conf->headers_set, size);
|
||||
if (copy == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
copy->code = ngx_http_script_copy_code;
|
||||
@ -2169,14 +2409,14 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
|
||||
if (code == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*code = (uintptr_t) NULL;
|
||||
|
||||
code = ngx_array_push_n(conf->headers_set, sizeof(uintptr_t));
|
||||
if (code == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*code = (uintptr_t) NULL;
|
||||
@ -2184,7 +2424,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
|
||||
code = ngx_array_push_n(conf->headers_set_len, sizeof(uintptr_t));
|
||||
if (code == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*code = (uintptr_t) NULL;
|
||||
@ -2202,10 +2442,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
conf->headers_names->nelts)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -2298,16 +2538,16 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_http_proxy_set_vars(cf->pool, &u, &plcf->vars) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
plcf->vars.schema.len = add;
|
||||
plcf->vars.schema.data = url->data;
|
||||
plcf->location = clcf->name;
|
||||
plcf->vars.key_start = plcf->vars.schema;
|
||||
|
||||
ngx_http_proxy_set_vars(&u, &plcf->vars);
|
||||
|
||||
clcf->handler = ngx_http_proxy_handler;
|
||||
|
||||
plcf->location = clcf->name;
|
||||
|
||||
if (clcf->named
|
||||
#if (NGX_PCRE)
|
||||
|| clcf->regex
|
||||
@ -2473,6 +2713,38 @@ ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
static char *
|
||||
ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
ngx_http_proxy_loc_conf_t *plcf = conf;
|
||||
|
||||
ngx_str_t *value;
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
if (plcf->upstream.cache != NGX_CONF_UNSET_PTR) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
if (ngx_strcmp(value[1].data, "off") == 0) {
|
||||
plcf->upstream.cache = NULL;
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
plcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0,
|
||||
&ngx_http_proxy_module);
|
||||
if (plcf->upstream.cache == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static char *
|
||||
ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
|
||||
{
|
||||
@ -2563,12 +2835,13 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_proxy_set_vars(ngx_pool_t *pool, ngx_url_t *u,
|
||||
ngx_http_proxy_vars_t *v)
|
||||
static void
|
||||
ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v)
|
||||
{
|
||||
if (u->family != AF_UNIX) {
|
||||
|
||||
if (u->no_port || u->port == u->default_port) {
|
||||
|
||||
v->host_header = u->host;
|
||||
|
||||
if (u->default_port == 80) {
|
||||
@ -2586,14 +2859,15 @@ ngx_http_proxy_set_vars(ngx_pool_t *pool, ngx_url_t *u,
|
||||
v->port = u->port_text;
|
||||
}
|
||||
|
||||
v->key_start.len += v->host_header.len;
|
||||
|
||||
} else {
|
||||
v->host_header.len = sizeof("localhost") - 1;
|
||||
v->host_header.data = (u_char *) "localhost";
|
||||
v->port.len = 0;
|
||||
v->port.data = (u_char *) "";
|
||||
v->key_start.len += sizeof("unix:") - 1 + u->host.len + 1;
|
||||
}
|
||||
|
||||
v->uri = u->uri;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
@ -199,6 +199,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
|
||||
ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
|
||||
|
||||
r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
|
||||
r->headers_out.status_line.len = 0;
|
||||
|
||||
if (ctx->ranges.nelts == 1) {
|
||||
return ngx_http_range_singlepart_header(r, ctx);
|
||||
@ -708,6 +709,7 @@ static ngx_int_t
|
||||
ngx_http_range_multipart_body(ngx_http_request_t *r,
|
||||
ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
|
||||
{
|
||||
off_t body_start;
|
||||
ngx_buf_t *b, *buf;
|
||||
ngx_uint_t i;
|
||||
ngx_chain_t *out, *hcl, *rcl, *dcl, **ll;
|
||||
@ -717,6 +719,12 @@ ngx_http_range_multipart_body(ngx_http_request_t *r,
|
||||
buf = in->buf;
|
||||
range = ctx->ranges.elts;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
body_start = r->cached ? r->cache->body_start : 0;
|
||||
#else
|
||||
body_start = 0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ctx->ranges.nelts; i++) {
|
||||
|
||||
/*
|
||||
@ -777,8 +785,8 @@ ngx_http_range_multipart_body(ngx_http_request_t *r,
|
||||
b->file = buf->file;
|
||||
|
||||
if (buf->in_file) {
|
||||
b->file_pos = range[i].start;
|
||||
b->file_last = range[i].end;
|
||||
b->file_pos = body_start + range[i].start;
|
||||
b->file_last = body_start + range[i].end;
|
||||
}
|
||||
|
||||
if (ngx_buf_in_memory(buf)) {
|
||||
|
@ -10,12 +10,13 @@
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_garbage_collector.h>
|
||||
|
||||
|
||||
typedef struct ngx_http_request_s ngx_http_request_t;
|
||||
typedef struct ngx_http_upstream_s ngx_http_upstream_t;
|
||||
typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t;
|
||||
typedef struct ngx_http_request_s ngx_http_request_t;
|
||||
typedef struct ngx_http_upstream_s ngx_http_upstream_t;
|
||||
typedef struct ngx_http_cache_s ngx_http_cache_t;
|
||||
typedef struct ngx_http_file_cache_s ngx_http_file_cache_t;
|
||||
typedef struct ngx_http_log_ctx_s ngx_http_log_ctx_t;
|
||||
|
||||
typedef ngx_int_t (*ngx_http_header_handler_pt)(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
@ -23,12 +24,6 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r,
|
||||
ngx_http_request_t *sr, u_char *buf, size_t len);
|
||||
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
#include <ngx_http_cache.h>
|
||||
#endif
|
||||
/* STUB */
|
||||
#include <ngx_http_cache.h>
|
||||
|
||||
#include <ngx_http_variables.h>
|
||||
#include <ngx_http_request.h>
|
||||
#include <ngx_http_upstream.h>
|
||||
@ -38,6 +33,9 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r,
|
||||
#include <ngx_http_script.h>
|
||||
#include <ngx_http_core_module.h>
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
#include <ngx_http_cache.h>
|
||||
#endif
|
||||
#if (NGX_HTTP_SSI)
|
||||
#include <ngx_http_ssi_filter_module.h>
|
||||
#endif
|
||||
|
@ -1,576 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Igor Sysoev
|
||||
*/
|
||||
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static ngx_http_module_t ngx_http_cache_module_ctx = {
|
||||
NULL, /* pre conf */
|
||||
|
||||
NULL, /* create main configuration */
|
||||
NULL, /* init main configuration */
|
||||
|
||||
NULL, /* create server configuration */
|
||||
NULL, /* merge server configuration */
|
||||
|
||||
NULL, /* create location configuration */
|
||||
NULL /* merge location configuration */
|
||||
};
|
||||
|
||||
|
||||
ngx_module_t ngx_http_cache_module = {
|
||||
NGX_MODULE,
|
||||
&ngx_http_cache_module_ctx, /* module context */
|
||||
NULL, /* module directives */
|
||||
NGX_HTTP_MODULE, /* module type */
|
||||
NULL, /* init module */
|
||||
NULL /* init process */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t ngx_http_cache_create(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_str_t *key;
|
||||
|
||||
if (!(r->cache = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t)))) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_array_init(&r->cache->key, r->pool, 5, sizeof(ngx_str_t))
|
||||
== NGX_ERROR)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* preallocate the primary key */
|
||||
|
||||
if (!(key = ngx_array_push(&r->cache->key))) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
key->len = 0;
|
||||
key->data = NULL;
|
||||
|
||||
/*
|
||||
* we use offsetof() because sizeof() pads the struct size to the int size
|
||||
*/
|
||||
|
||||
r->cache->header_size = offsetof(ngx_http_cache_header_t, key);
|
||||
|
||||
r->cache->log = r->connection->log;
|
||||
r->cache->file.log = r->connection->log;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_http_cache_get(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx)
|
||||
{
|
||||
ngx_str_t *key;
|
||||
ngx_http_cache_t *c;
|
||||
|
||||
if (r->cache == NULL) {
|
||||
if (ngx_http_cache_create(r) == NGX_ERROR) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
c = r->cache;
|
||||
key = c->key.elts;
|
||||
|
||||
if (ctx->primary) {
|
||||
key[0] = ctx->key;
|
||||
c->header_size += ctx->key.len;
|
||||
c->key_len += ctx->key.len;
|
||||
c->buf = ctx->buf;
|
||||
|
||||
} else {
|
||||
if (key[0].len == 0) {
|
||||
key[0] = r->uri;
|
||||
c->header_size += r->uri.len;
|
||||
c->key_len += ctx->key.len;
|
||||
}
|
||||
|
||||
if (!(key = ngx_array_push(&r->cache->key))) {
|
||||
return NGX_ABORT;
|
||||
}
|
||||
|
||||
c->header_size += ctx->key.len;
|
||||
c->key_len += ctx->key.len;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
if (ctx->memory) {
|
||||
ngx_http_memory_cache_get(r, ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (ctx->file) {
|
||||
return ngx_http_file_cache_get(r, ctx);
|
||||
}
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *hash,
|
||||
ngx_http_cleanup_t *cleanup,
|
||||
ngx_str_t *key, uint32_t *crc)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
ngx_http_cache_t *c;
|
||||
|
||||
*crc = ngx_crc(key->data, key->len);
|
||||
|
||||
c = hash->elts + *crc % hash->hash * hash->nelts;
|
||||
|
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) {
|
||||
return (void *) NGX_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < hash->nelts; i++) {
|
||||
if (c[i].crc == *crc
|
||||
&& c[i].key.len == key->len
|
||||
&& ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0)
|
||||
{
|
||||
#if 0
|
||||
if (c[i].expired) {
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
return (void *) NGX_AGAIN;
|
||||
}
|
||||
#endif
|
||||
|
||||
c[i].refs++;
|
||||
|
||||
if ((!(c[i].notify && (ngx_event_flags & NGX_USE_KQUEUE_EVENT)))
|
||||
&& (ngx_cached_time - c[i].updated >= hash->update))
|
||||
{
|
||||
c[i].expired = 1;
|
||||
}
|
||||
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
|
||||
if (cleanup) {
|
||||
cleanup->data.cache.hash = hash;
|
||||
cleanup->data.cache.cache = &c[i];
|
||||
cleanup->valid = 1;
|
||||
cleanup->cache = 1;
|
||||
}
|
||||
|
||||
return &c[i];
|
||||
}
|
||||
}
|
||||
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *hash,
|
||||
ngx_http_cache_t *cache,
|
||||
ngx_http_cleanup_t *cleanup,
|
||||
ngx_str_t *key, uint32_t crc,
|
||||
ngx_str_t *value, ngx_log_t *log)
|
||||
{
|
||||
time_t old;
|
||||
ngx_uint_t i;
|
||||
ngx_http_cache_t *c;
|
||||
|
||||
old = ngx_cached_time + 1;
|
||||
|
||||
c = hash->elts + crc % hash->hash * hash->nelts;
|
||||
|
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) {
|
||||
return (void *) NGX_ERROR;
|
||||
}
|
||||
|
||||
if (cache == NULL) {
|
||||
|
||||
/* allocate a new entry */
|
||||
|
||||
for (i = 0; i < hash->nelts; i++) {
|
||||
if (c[i].refs > 0) {
|
||||
/* a busy entry */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c[i].key.len == 0) {
|
||||
/* a free entry is found */
|
||||
cache = &c[i];
|
||||
break;
|
||||
}
|
||||
|
||||
/* looking for the oldest cache entry */
|
||||
|
||||
if (old > c[i].accessed) {
|
||||
|
||||
old = c[i].accessed;
|
||||
cache = &c[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (cache == NULL) {
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ngx_http_cache_free(cache, key, value, log);
|
||||
|
||||
if (cache->key.data == NULL) {
|
||||
cache->key.data = ngx_alloc(key->len, log);
|
||||
if (cache->key.data == NULL) {
|
||||
ngx_http_cache_free(cache, NULL, NULL, log);
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
cache->key.len = key->len;
|
||||
ngx_memcpy(cache->key.data, key->data, key->len);
|
||||
|
||||
} else if (value) {
|
||||
ngx_http_cache_free(cache, key, value, log);
|
||||
}
|
||||
|
||||
if (value) {
|
||||
if (cache->data.value.data == NULL) {
|
||||
cache->data.value.data = ngx_alloc(value->len, log);
|
||||
if (cache->data.value.data == NULL) {
|
||||
ngx_http_cache_free(cache, NULL, NULL, log);
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
cache->data.value.len = value->len;
|
||||
ngx_memcpy(cache->data.value.data, value->data, value->len);
|
||||
}
|
||||
|
||||
cache->crc = crc;
|
||||
cache->key.len = key->len;
|
||||
|
||||
cache->refs = 1;
|
||||
cache->count = 0;
|
||||
|
||||
cache->deleted = 0;
|
||||
cache->expired = 0;
|
||||
cache->memory = 0;
|
||||
cache->mmap = 0;
|
||||
cache->notify = 0;
|
||||
|
||||
if (cleanup) {
|
||||
cleanup->data.cache.hash = hash;
|
||||
cleanup->data.cache.cache = cache;
|
||||
cleanup->valid = 1;
|
||||
cleanup->cache = 1;
|
||||
}
|
||||
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
void ngx_http_cache_free(ngx_http_cache_t *cache,
|
||||
ngx_str_t *key, ngx_str_t *value, ngx_log_t *log)
|
||||
{
|
||||
if (cache->memory) {
|
||||
if (cache->data.value.data
|
||||
&& (value == NULL || value->len > cache->data.value.len))
|
||||
{
|
||||
ngx_free(cache->data.value.data);
|
||||
cache->data.value.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: mmap */
|
||||
|
||||
cache->data.value.len = 0;
|
||||
|
||||
if (cache->fd != NGX_INVALID_FILE) {
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
|
||||
"http cache close fd: %d", cache->fd);
|
||||
|
||||
if (ngx_close_file(cache->fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
ngx_close_file_n " \"%s\" failed",
|
||||
cache->key.data);
|
||||
}
|
||||
|
||||
cache->fd = NGX_INVALID_FILE;
|
||||
}
|
||||
|
||||
if (cache->key.data && (key == NULL || key->len > cache->key.len)) {
|
||||
ngx_free(cache->key.data);
|
||||
cache->key.data = NULL;
|
||||
}
|
||||
|
||||
cache->key.len = 0;
|
||||
|
||||
cache->refs = 0;
|
||||
}
|
||||
|
||||
|
||||
void ngx_http_cache_lock(ngx_http_cache_hash_t *hash, ngx_http_cache_t *cache)
|
||||
{
|
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash,
|
||||
ngx_http_cache_t *cache, ngx_log_t *log)
|
||||
{
|
||||
if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache->refs--;
|
||||
|
||||
if (cache->refs == 0 && cache->deleted) {
|
||||
ngx_http_cache_free(cache, NULL, NULL, log);
|
||||
}
|
||||
|
||||
ngx_mutex_unlock(&hash->mutex);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
ngx_http_cache_add_file_event(ngx_http_cache_hash_t *hash,
|
||||
ngx_http_cache_t *cache)
|
||||
{
|
||||
ngx_event_t *ev;
|
||||
ngx_http_cache_event_ctx_t *ctx;
|
||||
|
||||
ev = &ngx_cycle->read_events[fd];
|
||||
ngx_memzero(ev, sizeof(ngx_event_t);
|
||||
|
||||
ev->data = data;
|
||||
ev->event_handler = ngx_http_cache_invalidate;
|
||||
|
||||
return ngx_add_event(ev, NGX_VNODE_EVENT, 0);
|
||||
}
|
||||
|
||||
|
||||
void ngx_http_cache_invalidate(ngx_event_t *ev)
|
||||
{
|
||||
ngx_http_cache_event_ctx_t *ctx;
|
||||
|
||||
ctx = ev->data;
|
||||
|
||||
ngx_http_cache_lock(&ctx->hash->mutex);
|
||||
|
||||
if (ctx->cache->refs == 0)
|
||||
ngx_http_cache_free(ctx->cache, NULL, NULL, ctx->log);
|
||||
|
||||
} else {
|
||||
ctx->cache->deleted = 1;
|
||||
}
|
||||
|
||||
ngx_http_cache_unlock(&ctx->hash->mutex);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* TODO: currently fd only */
|
||||
|
||||
ngx_int_t ngx_http_send_cached(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_hunk_t *h;
|
||||
ngx_chain_t out;
|
||||
ngx_http_log_ctx_t *ctx;
|
||||
|
||||
ctx = r->connection->log->data;
|
||||
ctx->action = "sending response to client";
|
||||
|
||||
r->headers_out.status = NGX_HTTP_OK;
|
||||
r->headers_out.content_length_n = r->cache->data.size;
|
||||
r->headers_out.last_modified_time = r->cache->last_modified;
|
||||
|
||||
if (ngx_http_set_content_type(r) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
/* we need to allocate all before the header would be sent */
|
||||
|
||||
if (!(h = ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)))) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (!(h->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)))) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
rc = ngx_http_send_header(r);
|
||||
|
||||
if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
h->type = r->main ? NGX_HUNK_FILE : NGX_HUNK_FILE|NGX_HUNK_LAST;
|
||||
|
||||
h->file_pos = 0;
|
||||
h->file_last = r->cache->data.size;
|
||||
|
||||
h->file->fd = r->cache->fd;
|
||||
h->file->log = r->connection->log;
|
||||
|
||||
out.hunk = h;
|
||||
out.next = NULL;
|
||||
|
||||
return ngx_http_output_filter(r, &out);
|
||||
}
|
||||
|
||||
|
||||
char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
char *p = conf;
|
||||
|
||||
ngx_int_t i, j, dup, invalid;
|
||||
ngx_str_t *value, line;
|
||||
ngx_http_cache_t *c;
|
||||
ngx_http_cache_hash_t *ch, **chp;
|
||||
|
||||
chp = (ngx_http_cache_hash_t **) (p + cmd->offset);
|
||||
if (*chp) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
if (!(ch = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_hash_t)))) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
*chp = ch;
|
||||
|
||||
dup = 0;
|
||||
invalid = 0;
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
for (i = 1; i < cf->args->nelts; i++) {
|
||||
|
||||
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 'h':
|
||||
if (ch->hash) {
|
||||
dup = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ch->hash = ngx_atoi(value[i].data + 2, value[i].len - 2);
|
||||
if (ch->hash == (size_t) NGX_ERROR || ch->hash == 0) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
case 'n':
|
||||
if (ch->nelts) {
|
||||
dup = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
ch->nelts = ngx_atoi(value[i].data + 2, value[i].len - 2);
|
||||
if (ch->nelts == (size_t) NGX_ERROR || ch->nelts == 0) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
case 'l':
|
||||
if (ch->life) {
|
||||
dup = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
line.len = value[i].len - 2;
|
||||
line.data = value[i].data + 2;
|
||||
|
||||
ch->life = ngx_parse_time(&line, 1);
|
||||
if (ch->life == NGX_ERROR || ch->life == 0) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
case 'u':
|
||||
if (ch->update) {
|
||||
dup = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
line.len = value[i].len - 2;
|
||||
line.data = value[i].data + 2;
|
||||
|
||||
ch->update = ngx_parse_time(&line, 1);
|
||||
if (ch->update == NGX_ERROR || ch->update == 0) {
|
||||
invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
default:
|
||||
invalid = 1;
|
||||
}
|
||||
|
||||
if (dup) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"duplicate value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
if (invalid) {
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||
"invalid value \"%s\"", value[i].data);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ch->elts = ngx_pcalloc(cf->pool,
|
||||
ch->hash * ch->nelts * sizeof(ngx_http_cache_t));
|
||||
if (ch->elts == NULL) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < (ngx_int_t) ch->hash; i++) {
|
||||
c = ch->elts + i * ch->nelts;
|
||||
|
||||
for (j = 0; j < (ngx_int_t) ch->nelts; j++) {
|
||||
c[j].fd = NGX_INVALID_FILE;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -13,145 +13,115 @@
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
/*
|
||||
* The 3 bits allows the 7 uses before the cache entry allocation.
|
||||
* We can use maximum 7 bits, i.e up to the 127 uses.
|
||||
*/
|
||||
#define NGX_HTTP_CACHE_LAZY_ALLOCATION_BITS 3
|
||||
/**/
|
||||
#define NGX_HTTP_CACHE_STALE 1
|
||||
#define NGX_HTTP_CACHE_AGED 2
|
||||
#define NGX_HTTP_CACHE_THE_SAME 3
|
||||
/**/
|
||||
|
||||
#define NGX_HTTP_CACHE_KEY_LEN 16
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t crc;
|
||||
ngx_str_t key;
|
||||
time_t accessed;
|
||||
ngx_uint_t status;
|
||||
time_t valid;
|
||||
} ngx_http_cache_valid_t;
|
||||
|
||||
unsigned refs:20; /* 1048576 references */
|
||||
|
||||
unsigned count:NGX_HTTP_CACHE_LAZY_ALLOCATION_BITS;
|
||||
/* ngx_http_file_cache_node_t takes exactly 64 bytes on FreeBSD/i386 */
|
||||
|
||||
unsigned deleted:1;
|
||||
unsigned expired:1;
|
||||
unsigned memory:1;
|
||||
unsigned mmap:1;
|
||||
unsigned notify:1;
|
||||
typedef struct {
|
||||
ngx_rbtree_node_t node;
|
||||
ngx_queue_t queue;
|
||||
|
||||
ngx_fd_t fd;
|
||||
#if (NGX_USE_HTTP_FILE_CACHE_UNIQ)
|
||||
ngx_file_uniq_t uniq; /* no needed with kqueue */
|
||||
#endif
|
||||
time_t last_modified;
|
||||
time_t updated;
|
||||
u_char key[NGX_HTTP_CACHE_KEY_LEN
|
||||
- sizeof(ngx_rbtree_key_t)];
|
||||
|
||||
union {
|
||||
off_t size;
|
||||
ngx_str_t value;
|
||||
} data;
|
||||
} ngx_http_cache_entry_t;
|
||||
unsigned count:20;
|
||||
unsigned uses:10;
|
||||
unsigned valid_msec:10;
|
||||
unsigned error:10;
|
||||
/* 7 unused bits */
|
||||
unsigned exists:1;
|
||||
|
||||
ngx_file_uniq_t uniq;
|
||||
time_t expire;
|
||||
time_t valid_sec;
|
||||
size_t body_start;
|
||||
} ngx_http_file_cache_node_t;
|
||||
|
||||
|
||||
struct ngx_http_cache_s {
|
||||
ngx_file_t file;
|
||||
ngx_array_t keys;
|
||||
uint32_t crc32;
|
||||
u_char key[NGX_HTTP_CACHE_KEY_LEN];
|
||||
|
||||
ngx_file_uniq_t uniq;
|
||||
time_t valid_sec;
|
||||
time_t last_modified;
|
||||
time_t date;
|
||||
|
||||
size_t header_start;
|
||||
size_t body_start;
|
||||
off_t length;
|
||||
|
||||
ngx_uint_t min_uses;
|
||||
ngx_uint_t uses;
|
||||
ngx_uint_t error;
|
||||
ngx_uint_t valid_msec;
|
||||
|
||||
ngx_buf_t *buf;
|
||||
|
||||
ngx_http_file_cache_t *file_cache;
|
||||
ngx_http_file_cache_node_t *node;
|
||||
|
||||
unsigned updated:1;
|
||||
unsigned exists:1;
|
||||
unsigned temp_file:1;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
time_t expires;
|
||||
time_t last_modified;
|
||||
time_t date;
|
||||
off_t length;
|
||||
size_t key_len;
|
||||
char key[1];
|
||||
} ngx_http_cache_header_t;
|
||||
time_t valid_sec;
|
||||
time_t last_modified;
|
||||
time_t date;
|
||||
uint32_t crc32;
|
||||
u_short valid_msec;
|
||||
u_short header_start;
|
||||
u_short body_start;
|
||||
} ngx_http_file_cache_header_t;
|
||||
|
||||
|
||||
#define NGX_HTTP_CACHE_HASH 7
|
||||
#define NGX_HTTP_CACHE_NELTS 4
|
||||
struct ngx_http_file_cache_s {
|
||||
ngx_rbtree_t *rbtree;
|
||||
ngx_queue_t *queue;
|
||||
ngx_slab_pool_t *shpool;
|
||||
|
||||
typedef struct {
|
||||
ngx_http_cache_entry_t *elts;
|
||||
size_t hash;
|
||||
size_t nelts;
|
||||
time_t life;
|
||||
time_t update;
|
||||
#if (NGX_THREADS)
|
||||
ngx_mutex_t mutex;
|
||||
#endif
|
||||
ngx_pool_t *pool;
|
||||
} ngx_http_cache_hash_t;
|
||||
ngx_path_t *path;
|
||||
|
||||
time_t inactive;
|
||||
time_t created;
|
||||
time_t clean_time;
|
||||
time_t next_clean_time;
|
||||
|
||||
ngx_shm_zone_t *shm_zone;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_http_cache_hash_t *hash;
|
||||
ngx_http_cache_entry_t *cache;
|
||||
ngx_file_t file;
|
||||
ngx_array_t key;
|
||||
uint32_t crc;
|
||||
u_char md5[16];
|
||||
ngx_path_t *path;
|
||||
ngx_buf_t *buf;
|
||||
time_t expires;
|
||||
time_t last_modified;
|
||||
time_t date;
|
||||
off_t length;
|
||||
size_t key_len;
|
||||
size_t file_start;
|
||||
ngx_file_uniq_t uniq;
|
||||
ngx_log_t *log;
|
||||
|
||||
/* STUB */
|
||||
ssize_t header_size;
|
||||
ngx_str_t key0;
|
||||
} ngx_http_cache_t;
|
||||
void ngx_http_file_cache_create_key(ngx_http_request_t *r);
|
||||
ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r);
|
||||
void ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf);
|
||||
void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf);
|
||||
ngx_int_t ngx_http_cache_send(ngx_http_request_t *);
|
||||
void ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf);
|
||||
time_t ngx_http_file_cache_valid(ngx_array_t *cache_valid, ngx_uint_t status);
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_path_t *path;
|
||||
ngx_str_t key;
|
||||
ngx_buf_t *buf;
|
||||
|
||||
unsigned file:1;
|
||||
unsigned memory:1;
|
||||
unsigned primary:1;
|
||||
} ngx_http_cache_ctx_t;
|
||||
|
||||
|
||||
#define NGX_HTTP_CACHE_STALE 1
|
||||
#define NGX_HTTP_CACHE_AGED 2
|
||||
#define NGX_HTTP_CACHE_THE_SAME 3
|
||||
|
||||
|
||||
ngx_int_t ngx_http_cache_get(ngx_http_request_t *r, ngx_http_cache_ctx_t *ctx);
|
||||
|
||||
ngx_int_t ngx_http_file_cache_get(ngx_http_request_t *r,
|
||||
ngx_http_cache_ctx_t *ctx);
|
||||
|
||||
ngx_int_t ngx_http_file_cache_open(ngx_http_cache_t *c);
|
||||
|
||||
ngx_int_t ngx_http_cache_cleaner_handler(ngx_gc_t *gc, ngx_str_t *name,
|
||||
ngx_dir_t *dir);
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *cache,
|
||||
ngx_http_cleanup_t *cleanup,
|
||||
ngx_str_t *key, uint32_t *crc);
|
||||
|
||||
ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *hash,
|
||||
ngx_http_cache_t *cache,
|
||||
ngx_http_cleanup_t *cleanup,
|
||||
ngx_str_t *key, uint32_t crc,
|
||||
ngx_str_t *value, ngx_log_t *log);
|
||||
void ngx_http_cache_free(ngx_http_cache_t *cache,
|
||||
ngx_str_t *key, ngx_str_t *value, ngx_log_t *log);
|
||||
void ngx_http_cache_lock(ngx_http_cache_hash_t *hash, ngx_http_cache_t *cache);
|
||||
void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash,
|
||||
ngx_http_cache_t *cache, ngx_log_t *log);
|
||||
|
||||
int ngx_http_cache_update_file(ngx_http_request_t *r,ngx_http_cache_ctx_t *ctx,
|
||||
ngx_str_t *temp_file);
|
||||
|
||||
int ngx_http_send_cached(ngx_http_request_t *r);
|
||||
|
||||
|
||||
char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||
|
||||
#endif
|
||||
char *ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
char *ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
|
||||
#endif /* _NGX_HTTP_CACHE_H_INCLUDED_ */
|
||||
|
@ -119,6 +119,11 @@ static ngx_conf_enum_t ngx_http_core_if_modified_since[] = {
|
||||
};
|
||||
|
||||
|
||||
static ngx_path_init_t ngx_http_client_temp_path = {
|
||||
ngx_string(NGX_HTTP_CLIENT_TEMP_PATH), { 0, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
|
||||
static ngx_conf_enum_t ngx_http_gzip_http_version[] = {
|
||||
@ -347,7 +352,7 @@ static ngx_command_t ngx_http_core_commands[] = {
|
||||
ngx_conf_set_path_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_core_loc_conf_t, client_body_temp_path),
|
||||
(void *) ngx_garbage_collector_temp_handler },
|
||||
NULL },
|
||||
|
||||
{ ngx_string("client_body_in_file_only"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
@ -2185,6 +2190,10 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
|
||||
|
||||
ngx_http_update_location_config(r);
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
r->cache = NULL;
|
||||
#endif
|
||||
|
||||
r->internal = 1;
|
||||
|
||||
ngx_http_handler(r);
|
||||
@ -3156,10 +3165,13 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
conf->resolver = prev->resolver;
|
||||
}
|
||||
|
||||
ngx_conf_merge_path_value(conf->client_body_temp_path,
|
||||
if (ngx_conf_merge_path_value(cf, &conf->client_body_temp_path,
|
||||
prev->client_body_temp_path,
|
||||
NGX_HTTP_CLIENT_TEMP_PATH, 0, 0, 0,
|
||||
ngx_garbage_collector_temp_handler, cf);
|
||||
&ngx_http_client_temp_path)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
ngx_conf_merge_value(conf->reset_timedout_connection,
|
||||
prev->reset_timedout_connection, 0);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -348,7 +348,9 @@ struct ngx_http_request_s {
|
||||
ngx_http_event_handler_pt read_event_handler;
|
||||
ngx_http_event_handler_pt write_event_handler;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
ngx_http_cache_t *cache;
|
||||
#endif
|
||||
|
||||
ngx_http_upstream_t *upstream;
|
||||
ngx_array_t *upstream_states;
|
||||
@ -443,6 +445,9 @@ struct ngx_http_request_s {
|
||||
unsigned subrequest_in_memory:1;
|
||||
unsigned waited:1;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
unsigned cached:1;
|
||||
#endif
|
||||
unsigned gzip:2;
|
||||
|
||||
unsigned proxy:1;
|
||||
|
@ -9,6 +9,13 @@
|
||||
#include <ngx_http.h>
|
||||
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u);
|
||||
static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u);
|
||||
#endif
|
||||
|
||||
static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
|
||||
static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
|
||||
static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
|
||||
@ -29,6 +36,8 @@ static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
|
||||
static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u);
|
||||
static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
|
||||
static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u);
|
||||
static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u);
|
||||
static void ngx_http_upstream_send_response(ngx_http_request_t *r,
|
||||
@ -80,10 +89,15 @@ static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset);
|
||||
@ -139,8 +153,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
||||
{ ngx_string("Last-Modified"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, last_modified),
|
||||
ngx_http_upstream_copy_header_line,
|
||||
offsetof(ngx_http_headers_out_t, last_modified), 0 },
|
||||
ngx_http_upstream_copy_last_modified, 0, 0 },
|
||||
|
||||
{ ngx_string("Server"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
@ -185,7 +198,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
||||
{ ngx_string("Accept-Ranges"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
|
||||
ngx_http_upstream_copy_header_line,
|
||||
ngx_http_upstream_copy_allow_ranges,
|
||||
offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
|
||||
|
||||
{ ngx_string("Connection"),
|
||||
@ -360,6 +373,25 @@ ngx_http_upstream_init(ngx_http_request_t *r)
|
||||
u->request_bufs = r->request_body->bufs;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (u->conf->cache) {
|
||||
ngx_int_t rc;
|
||||
|
||||
rc = ngx_http_upstream_cache(r, u);
|
||||
|
||||
if (rc == NGX_DONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rc != NGX_DECLINED) {
|
||||
ngx_http_finalize_request(r, rc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (u->create_request(r) != NGX_OK) {
|
||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
@ -491,6 +523,136 @@ found:
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_cache_t *c;
|
||||
|
||||
c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
|
||||
if (c == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->cache = c;
|
||||
c->file.log = r->connection->log;
|
||||
|
||||
if (u->create_key(r) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: add keys */
|
||||
|
||||
ngx_http_file_cache_create_key(r);
|
||||
|
||||
u->cacheable = 1;
|
||||
|
||||
c->min_uses = r->upstream->conf->cache_min_uses;
|
||||
c->body_start = r->upstream->conf->buffer_size;
|
||||
c->file_cache = u->conf->cache->data;
|
||||
|
||||
rc = ngx_http_file_cache_open(r);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http upstream cache: %i u:%ui", rc, c->uses);
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
|
||||
rc = ngx_http_upstream_cache_send(r, u);
|
||||
|
||||
if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
} else if (rc == NGX_ERROR) {
|
||||
|
||||
return NGX_ERROR;
|
||||
|
||||
} else if (rc == NGX_HTTP_CACHE_STALE) {
|
||||
|
||||
u->stale_cache = 1;
|
||||
u->buffer.start = NULL;
|
||||
|
||||
} else if (rc == NGX_DECLINED) {
|
||||
|
||||
if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
|
||||
u->buffer.start = NULL;
|
||||
|
||||
} else {
|
||||
u->buffer.pos = u->buffer.start + c->header_start;
|
||||
u->buffer.last = u->buffer.pos;
|
||||
}
|
||||
|
||||
} else if (rc == NGX_AGAIN) {
|
||||
|
||||
u->cacheable = 0;
|
||||
|
||||
} else {
|
||||
|
||||
/* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
r->cached = 0;
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_http_cache_t *c;
|
||||
|
||||
c = r->cache;
|
||||
|
||||
/* TODO: cache stack */
|
||||
|
||||
u->buffer = *c->buf;
|
||||
u->buffer.pos += c->header_start;
|
||||
|
||||
ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
|
||||
|
||||
if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
|
||||
sizeof(ngx_table_elt_t))
|
||||
!= NGX_OK)
|
||||
{
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
rc = u->process_header(r);
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
|
||||
if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
return ngx_http_cache_send(r);
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
/* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
|
||||
|
||||
/* TODO: delete file */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
|
||||
{
|
||||
@ -969,22 +1131,18 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
|
||||
/* reinit u->buffer */
|
||||
|
||||
#if 0
|
||||
if (u->cache) {
|
||||
u->buffer.pos = u->buffer.start + u->cache->ctx.header_size;
|
||||
u->buffer.last = u->buffer.pos;
|
||||
u->buffer.pos = u->buffer.start;
|
||||
|
||||
} else {
|
||||
u->buffer.pos = u->buffer.start;
|
||||
u->buffer.last = u->buffer.start;
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (r->cache) {
|
||||
u->buffer.pos += r->cache->header_start;
|
||||
}
|
||||
#else
|
||||
|
||||
u->buffer.pos = u->buffer.start;
|
||||
u->buffer.last = u->buffer.start;
|
||||
|
||||
#endif
|
||||
|
||||
u->buffer.last = u->buffer.pos;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
@ -1115,15 +1273,9 @@ ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
|
||||
static void
|
||||
ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
{
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t *uri, args;
|
||||
ngx_uint_t i, flags;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_upstream_header_t *hh;
|
||||
ngx_http_upstream_main_conf_t *umcf;
|
||||
ssize_t n;
|
||||
ngx_int_t rc;
|
||||
ngx_connection_t *c;
|
||||
|
||||
c = u->peer.connection;
|
||||
|
||||
@ -1166,9 +1318,10 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (u->cache) {
|
||||
u->buffer.pos += u->cache->ctx.header_size;
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (r->cache) {
|
||||
u->buffer.pos += r->cache->header_start;
|
||||
u->buffer.last = u->buffer.pos;
|
||||
}
|
||||
#endif
|
||||
@ -1257,124 +1410,10 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
}
|
||||
}
|
||||
|
||||
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
||||
|
||||
if (u->headers_in.x_accel_redirect) {
|
||||
|
||||
ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
|
||||
|
||||
part = &u->headers_in.headers.part;
|
||||
h = part->elts;
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
|
||||
if (i >= part->nelts) {
|
||||
if (part->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
part = part->next;
|
||||
h = part->elts;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len);
|
||||
|
||||
if (hh && hh->redirect) {
|
||||
if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
|
||||
ngx_http_finalize_request(r,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uri = &u->headers_in.x_accel_redirect->value;
|
||||
args.len = 0;
|
||||
args.data = NULL;
|
||||
flags = 0;
|
||||
|
||||
if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & NGX_HTTP_ZERO_IN_URI) {
|
||||
r->zero_in_uri = 1;
|
||||
}
|
||||
|
||||
if (r->method != NGX_HTTP_HEAD) {
|
||||
r->method = NGX_HTTP_GET;
|
||||
}
|
||||
|
||||
r->valid_unparsed_uri = 0;
|
||||
|
||||
ngx_http_internal_redirect(r, uri, &args);
|
||||
if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
part = &u->headers_in.headers.part;
|
||||
h = part->elts;
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
|
||||
if (i >= part->nelts) {
|
||||
if (part->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
part = part->next;
|
||||
h = part->elts;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len);
|
||||
|
||||
if (hh) {
|
||||
if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
|
||||
r->headers_out.server->hash = 0;
|
||||
}
|
||||
|
||||
if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
|
||||
r->headers_out.date->hash = 0;
|
||||
}
|
||||
|
||||
r->headers_out.status = u->headers_in.status_n;
|
||||
r->headers_out.status_line = u->headers_in.status_line;
|
||||
|
||||
u->headers_in.content_length_n = r->headers_out.content_length_n;
|
||||
|
||||
if (r->headers_out.content_length_n != -1) {
|
||||
u->length = (size_t) r->headers_out.content_length_n;
|
||||
|
||||
} else {
|
||||
u->length = NGX_MAX_SIZE_T_VALUE;
|
||||
}
|
||||
|
||||
if (!r->subrequest_in_memory) {
|
||||
ngx_http_upstream_send_response(r, u);
|
||||
return;
|
||||
@ -1443,9 +1482,12 @@ ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (u->peer.tries == 0 && u->stale && (u->conf->use_stale & un->mask)) {
|
||||
if (u->peer.tries == 0
|
||||
&& u->stale_cache
|
||||
&& (u->conf->cache_use_stale & un->mask))
|
||||
{
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
ngx_http_send_cached_response(r));
|
||||
ngx_http_upstream_cache_send(r, u));
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
@ -1557,6 +1599,138 @@ ngx_http_upstream_test_connect(ngx_connection_t *c)
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
{
|
||||
ngx_str_t *uri, args;
|
||||
ngx_uint_t i, flags;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *h;
|
||||
ngx_http_upstream_header_t *hh;
|
||||
ngx_http_upstream_main_conf_t *umcf;
|
||||
|
||||
umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
|
||||
|
||||
if (u->headers_in.x_accel_redirect) {
|
||||
|
||||
ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
|
||||
|
||||
part = &u->headers_in.headers.part;
|
||||
h = part->elts;
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
|
||||
if (i >= part->nelts) {
|
||||
if (part->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
part = part->next;
|
||||
h = part->elts;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len);
|
||||
|
||||
if (hh && hh->redirect) {
|
||||
if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
|
||||
ngx_http_finalize_request(r,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return NGX_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uri = &u->headers_in.x_accel_redirect->value;
|
||||
args.len = 0;
|
||||
args.data = NULL;
|
||||
flags = 0;
|
||||
|
||||
if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
|
||||
ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
if (flags & NGX_HTTP_ZERO_IN_URI) {
|
||||
r->zero_in_uri = 1;
|
||||
}
|
||||
|
||||
if (r->method != NGX_HTTP_HEAD) {
|
||||
r->method = NGX_HTTP_GET;
|
||||
}
|
||||
|
||||
r->valid_unparsed_uri = 0;
|
||||
|
||||
ngx_http_internal_redirect(r, uri, &args);
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
part = &u->headers_in.headers.part;
|
||||
h = part->elts;
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
|
||||
if (i >= part->nelts) {
|
||||
if (part->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
part = part->next;
|
||||
h = part->elts;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
|
||||
h[i].lowcase_key, h[i].key.len);
|
||||
|
||||
if (hh) {
|
||||
if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||
return NGX_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (r->headers_out.server && r->headers_out.server->value.data == NULL) {
|
||||
r->headers_out.server->hash = 0;
|
||||
}
|
||||
|
||||
if (r->headers_out.date && r->headers_out.date->value.data == NULL) {
|
||||
r->headers_out.date->hash = 0;
|
||||
}
|
||||
|
||||
r->headers_out.status = u->headers_in.status_n;
|
||||
r->headers_out.status_line = u->headers_in.status_line;
|
||||
|
||||
u->headers_in.content_length_n = r->headers_out.content_length_n;
|
||||
|
||||
if (r->headers_out.content_length_n != -1) {
|
||||
u->length = (size_t) r->headers_out.content_length_n;
|
||||
|
||||
} else {
|
||||
u->length = NGX_MAX_SIZE_T_VALUE;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u)
|
||||
@ -1637,8 +1811,6 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
ngx_int_t rc;
|
||||
ngx_event_pipe_t *p;
|
||||
ngx_connection_t *c;
|
||||
ngx_pool_cleanup_t *cl;
|
||||
ngx_pool_cleanup_file_t *clf;
|
||||
ngx_http_core_loc_conf_t *clcf;
|
||||
|
||||
rc = ngx_http_send_header(r);
|
||||
@ -1651,18 +1823,8 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
u->header_sent = 1;
|
||||
|
||||
if (r->request_body && r->request_body->temp_file) {
|
||||
for (cl = r->pool->cleanup; cl; cl = cl->next) {
|
||||
if (cl->handler == ngx_pool_cleanup_file) {
|
||||
clf = cl->data;
|
||||
|
||||
if (clf->fd == r->request_body->temp_file->file.fd) {
|
||||
cl->handler(clf);
|
||||
cl->handler = NULL;
|
||||
r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
|
||||
r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
|
||||
}
|
||||
|
||||
c = r->connection;
|
||||
@ -1738,28 +1900,38 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
|
||||
/* TODO: preallocate event_pipe bufs, look "Content-Length" */
|
||||
|
||||
#if 0
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (u->cache && u->cache->ctx.file.fd != NGX_INVALID_FILE) {
|
||||
if (ngx_close_file(u->cache->ctx.file.fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
|
||||
ngx_close_file_n " \"%s\" failed",
|
||||
u->cache->ctx.file.name.data);
|
||||
}
|
||||
if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
|
||||
ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
|
||||
r->cache->file.fd = NGX_INVALID_FILE;
|
||||
}
|
||||
|
||||
if (u->cacheable) {
|
||||
header = (ngx_http_cache_header_t *) u->buffer->start;
|
||||
time_t now, valid;
|
||||
|
||||
header->expires = u->cache->ctx.expires;
|
||||
header->last_modified = u->cache->ctx.last_modified;
|
||||
header->date = u->cache->ctx.date;
|
||||
header->length = r->headers_out.content_length_n;
|
||||
u->cache->ctx.length = r->headers_out.content_length_n;
|
||||
valid = ngx_http_file_cache_valid(u->conf->cache_valid,
|
||||
u->headers_in.status_n);
|
||||
if (valid) {
|
||||
|
||||
header->key_len = u->cache->ctx.key0.len;
|
||||
ngx_memcpy(&header->key, u->cache->ctx.key0.data, header->key_len);
|
||||
header->key[header->key_len] = LF;
|
||||
now = ngx_time();
|
||||
|
||||
r->cache->valid_sec = now + valid;
|
||||
|
||||
r->cache->last_modified = r->headers_out.last_modified_time;
|
||||
r->cache->date = now;
|
||||
r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
|
||||
|
||||
if (r->headers_out.content_length_n != -1) {
|
||||
r->cache->length = r->cache->body_start
|
||||
+ r->headers_out.content_length_n;
|
||||
}
|
||||
|
||||
ngx_http_file_cache_set_header(r, u->buffer.start);
|
||||
|
||||
} else {
|
||||
u->cacheable = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1789,7 +1961,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
p->temp_file->path = u->conf->temp_path;
|
||||
p->temp_file->pool = r->pool;
|
||||
|
||||
if (u->cacheable || u->store) {
|
||||
if (p->cacheable) {
|
||||
p->temp_file->persistent = 1;
|
||||
|
||||
} else {
|
||||
@ -2241,23 +2413,21 @@ ngx_http_upstream_process_request(ngx_http_request_t *r)
|
||||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_FILE_CACHE)
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (p->upstream_done && u->cacheable) {
|
||||
if (ngx_http_cache_update(r) == NGX_ERROR) {
|
||||
ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
|
||||
ngx_http_upstream_finalize_request(r, u, 0);
|
||||
return;
|
||||
}
|
||||
if (u->cacheable) {
|
||||
|
||||
} else if (p->upstream_eof && u->cacheable) {
|
||||
if (p->upstream_done) {
|
||||
ngx_http_file_cache_update(r, u->pipe->temp_file);
|
||||
|
||||
/* TODO: check length & update cache */
|
||||
} else if (p->upstream_eof) {
|
||||
|
||||
if (ngx_http_cache_update(r) == NGX_ERROR) {
|
||||
ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
|
||||
ngx_http_upstream_finalize_request(r, u, 0);
|
||||
return;
|
||||
/* TODO: check length & update cache */
|
||||
|
||||
ngx_http_file_cache_update(r, u->pipe->temp_file);
|
||||
|
||||
} else if (p->upstream_error) {
|
||||
ngx_http_file_cache_free(r, u->pipe->temp_file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2438,12 +2608,12 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (u->stale && (u->conf->use_stale & ft_type)) {
|
||||
if (u->stale_cache && (u->conf->cache_use_stale & ft_type)) {
|
||||
|
||||
ngx_http_upstream_finalize_request(r, u,
|
||||
ngx_http_send_cached_response(r));
|
||||
ngx_http_upstream_cache_send(r, u));
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ngx_http_upstream_finalize_request(r, u, status);
|
||||
@ -2557,25 +2727,41 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
|
||||
|
||||
u->peer.connection = NULL;
|
||||
|
||||
if (u->header_sent && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
|
||||
{
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (u->pipe && u->pipe->temp_file) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http upstream temp fd: %d",
|
||||
u->pipe->temp_file->file.fd);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (u->cache) {
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (r->cache) {
|
||||
time_t valid;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http upstream cache fd: %d",
|
||||
u->cache->ctx.file.fd);
|
||||
r->cache->file.fd);
|
||||
|
||||
if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
|
||||
|
||||
valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
|
||||
|
||||
if (valid) {
|
||||
r->cache->valid_sec = ngx_time() + valid;
|
||||
r->cache->error = rc;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_http_file_cache_free(r, u->pipe->temp_file);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (u->header_sent && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
|
||||
{
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
if (rc == NGX_DECLINED) {
|
||||
return;
|
||||
}
|
||||
@ -2826,6 +3012,33 @@ ngx_http_upstream_copy_content_length(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
{
|
||||
ngx_table_elt_t *ho;
|
||||
|
||||
ho = ngx_list_push(&r->headers_out.headers);
|
||||
if (ho == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ho = *h;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (r->cached) {
|
||||
r->headers_out.last_modified = ho;
|
||||
r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
|
||||
h->value.len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
ngx_uint_t offset)
|
||||
@ -2916,6 +3129,33 @@ ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, ngx_uint_t offset)
|
||||
{
|
||||
ngx_table_elt_t *ho;
|
||||
|
||||
#if (NGX_HTTP_CACHE)
|
||||
|
||||
if (r->cached) {
|
||||
r->allow_ranges = 1;
|
||||
return NGX_OK;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
ho = ngx_list_push(&r->headers_out.headers);
|
||||
if (ho == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
*ho = *h;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
|
||||
static ngx_int_t
|
||||
|
@ -39,21 +39,21 @@
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_msec_t bl_time;
|
||||
ngx_uint_t bl_state;
|
||||
ngx_msec_t bl_time;
|
||||
ngx_uint_t bl_state;
|
||||
|
||||
ngx_uint_t status;
|
||||
time_t response_sec;
|
||||
ngx_uint_t response_msec;
|
||||
ngx_uint_t status;
|
||||
time_t response_sec;
|
||||
ngx_uint_t response_msec;
|
||||
off_t response_length;
|
||||
|
||||
ngx_str_t *peer;
|
||||
ngx_str_t *peer;
|
||||
} ngx_http_upstream_state_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_hash_t headers_in_hash;
|
||||
ngx_array_t upstreams;
|
||||
ngx_hash_t headers_in_hash;
|
||||
ngx_array_t upstreams;
|
||||
/* ngx_http_upstream_srv_conf_t */
|
||||
} ngx_http_upstream_main_conf_t;
|
||||
|
||||
@ -66,21 +66,21 @@ typedef ngx_int_t (*ngx_http_upstream_init_peer_pt)(ngx_http_request_t *r,
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_http_upstream_init_pt init_upstream;
|
||||
ngx_http_upstream_init_peer_pt init;
|
||||
void *data;
|
||||
ngx_http_upstream_init_pt init_upstream;
|
||||
ngx_http_upstream_init_peer_pt init;
|
||||
void *data;
|
||||
} ngx_http_upstream_peer_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_peer_addr_t *addrs;
|
||||
ngx_uint_t naddrs;
|
||||
ngx_uint_t weight;
|
||||
ngx_uint_t max_fails;
|
||||
time_t fail_timeout;
|
||||
ngx_peer_addr_t *addrs;
|
||||
ngx_uint_t naddrs;
|
||||
ngx_uint_t weight;
|
||||
ngx_uint_t max_fails;
|
||||
time_t fail_timeout;
|
||||
|
||||
unsigned down:1;
|
||||
unsigned backup:1;
|
||||
unsigned down:1;
|
||||
unsigned backup:1;
|
||||
} ngx_http_upstream_server_t;
|
||||
|
||||
|
||||
@ -93,67 +93,75 @@ typedef struct {
|
||||
|
||||
|
||||
struct ngx_http_upstream_srv_conf_s {
|
||||
ngx_http_upstream_peer_t peer;
|
||||
void **srv_conf;
|
||||
ngx_http_upstream_peer_t peer;
|
||||
void **srv_conf;
|
||||
|
||||
ngx_array_t *servers; /* ngx_http_upstream_server_t */
|
||||
ngx_array_t *servers; /* ngx_http_upstream_server_t */
|
||||
|
||||
ngx_uint_t flags;
|
||||
ngx_str_t host;
|
||||
u_char *file_name;
|
||||
ngx_uint_t line;
|
||||
in_port_t port;
|
||||
in_port_t default_port;
|
||||
ngx_uint_t flags;
|
||||
ngx_str_t host;
|
||||
u_char *file_name;
|
||||
ngx_uint_t line;
|
||||
in_port_t port;
|
||||
in_port_t default_port;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_http_upstream_srv_conf_t *upstream;
|
||||
ngx_http_upstream_srv_conf_t *upstream;
|
||||
|
||||
ngx_msec_t connect_timeout;
|
||||
ngx_msec_t send_timeout;
|
||||
ngx_msec_t read_timeout;
|
||||
ngx_msec_t timeout;
|
||||
ngx_msec_t connect_timeout;
|
||||
ngx_msec_t send_timeout;
|
||||
ngx_msec_t read_timeout;
|
||||
ngx_msec_t timeout;
|
||||
|
||||
size_t send_lowat;
|
||||
size_t buffer_size;
|
||||
size_t send_lowat;
|
||||
size_t buffer_size;
|
||||
|
||||
size_t busy_buffers_size;
|
||||
size_t max_temp_file_size;
|
||||
size_t temp_file_write_size;
|
||||
size_t busy_buffers_size;
|
||||
size_t max_temp_file_size;
|
||||
size_t temp_file_write_size;
|
||||
|
||||
size_t busy_buffers_size_conf;
|
||||
size_t max_temp_file_size_conf;
|
||||
size_t temp_file_write_size_conf;
|
||||
size_t busy_buffers_size_conf;
|
||||
size_t max_temp_file_size_conf;
|
||||
size_t temp_file_write_size_conf;
|
||||
|
||||
ngx_uint_t next_upstream;
|
||||
ngx_uint_t store_access;
|
||||
ngx_bufs_t bufs;
|
||||
|
||||
ngx_bufs_t bufs;
|
||||
ngx_uint_t next_upstream;
|
||||
ngx_uint_t store_access;
|
||||
ngx_flag_t buffering;
|
||||
ngx_flag_t pass_request_headers;
|
||||
ngx_flag_t pass_request_body;
|
||||
|
||||
ngx_flag_t buffering;
|
||||
ngx_flag_t pass_request_headers;
|
||||
ngx_flag_t pass_request_body;
|
||||
ngx_flag_t ignore_client_abort;
|
||||
ngx_flag_t intercept_errors;
|
||||
ngx_flag_t cyclic_temp_file;
|
||||
|
||||
ngx_flag_t ignore_client_abort;
|
||||
ngx_flag_t intercept_errors;
|
||||
ngx_flag_t cyclic_temp_file;
|
||||
ngx_path_t *temp_path;
|
||||
|
||||
ngx_path_t *temp_path;
|
||||
ngx_hash_t hide_headers_hash;
|
||||
ngx_array_t *hide_headers;
|
||||
ngx_array_t *pass_headers;
|
||||
|
||||
ngx_hash_t hide_headers_hash;
|
||||
ngx_array_t *hide_headers;
|
||||
ngx_array_t *pass_headers;
|
||||
#if (NGX_HTTP_CACHE)
|
||||
ngx_shm_zone_t *cache;
|
||||
|
||||
ngx_array_t *store_lengths;
|
||||
ngx_array_t *store_values;
|
||||
ngx_uint_t cache_min_uses;
|
||||
ngx_uint_t cache_use_stale;
|
||||
|
||||
signed store:2;
|
||||
unsigned intercept_404:1;
|
||||
unsigned change_buffering:1;
|
||||
ngx_array_t *cache_valid;
|
||||
#endif
|
||||
|
||||
ngx_array_t *store_lengths;
|
||||
ngx_array_t *store_values;
|
||||
|
||||
signed store:2;
|
||||
unsigned intercept_404:1;
|
||||
unsigned change_buffering:1;
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
ngx_ssl_t *ssl;
|
||||
ngx_ssl_t *ssl;
|
||||
ngx_flag_t ssl_session_reuse;
|
||||
#endif
|
||||
|
||||
@ -161,62 +169,62 @@ typedef struct {
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t name;
|
||||
ngx_http_header_handler_pt handler;
|
||||
ngx_uint_t offset;
|
||||
ngx_http_header_handler_pt copy_handler;
|
||||
ngx_uint_t conf;
|
||||
ngx_uint_t redirect; /* unsigned redirect:1; */
|
||||
ngx_str_t name;
|
||||
ngx_http_header_handler_pt handler;
|
||||
ngx_uint_t offset;
|
||||
ngx_http_header_handler_pt copy_handler;
|
||||
ngx_uint_t conf;
|
||||
ngx_uint_t redirect; /* unsigned redirect:1; */
|
||||
} ngx_http_upstream_header_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_list_t headers;
|
||||
ngx_list_t headers;
|
||||
|
||||
ngx_uint_t status_n;
|
||||
ngx_str_t status_line;
|
||||
ngx_uint_t status_n;
|
||||
ngx_str_t status_line;
|
||||
|
||||
ngx_table_elt_t *status;
|
||||
ngx_table_elt_t *date;
|
||||
ngx_table_elt_t *server;
|
||||
ngx_table_elt_t *connection;
|
||||
ngx_table_elt_t *status;
|
||||
ngx_table_elt_t *date;
|
||||
ngx_table_elt_t *server;
|
||||
ngx_table_elt_t *connection;
|
||||
|
||||
ngx_table_elt_t *expires;
|
||||
ngx_table_elt_t *etag;
|
||||
ngx_table_elt_t *x_accel_expires;
|
||||
ngx_table_elt_t *x_accel_redirect;
|
||||
ngx_table_elt_t *x_accel_limit_rate;
|
||||
ngx_table_elt_t *expires;
|
||||
ngx_table_elt_t *etag;
|
||||
ngx_table_elt_t *x_accel_expires;
|
||||
ngx_table_elt_t *x_accel_redirect;
|
||||
ngx_table_elt_t *x_accel_limit_rate;
|
||||
|
||||
ngx_table_elt_t *content_type;
|
||||
ngx_table_elt_t *content_length;
|
||||
ngx_table_elt_t *content_type;
|
||||
ngx_table_elt_t *content_length;
|
||||
|
||||
ngx_table_elt_t *last_modified;
|
||||
ngx_table_elt_t *location;
|
||||
ngx_table_elt_t *accept_ranges;
|
||||
ngx_table_elt_t *www_authenticate;
|
||||
ngx_table_elt_t *last_modified;
|
||||
ngx_table_elt_t *location;
|
||||
ngx_table_elt_t *accept_ranges;
|
||||
ngx_table_elt_t *www_authenticate;
|
||||
|
||||
#if (NGX_HTTP_GZIP)
|
||||
ngx_table_elt_t *content_encoding;
|
||||
ngx_table_elt_t *content_encoding;
|
||||
#endif
|
||||
|
||||
off_t content_length_n;
|
||||
off_t content_length_n;
|
||||
|
||||
ngx_array_t cache_control;
|
||||
ngx_array_t cache_control;
|
||||
} ngx_http_upstream_headers_in_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t host;
|
||||
in_port_t port;
|
||||
ngx_uint_t no_port; /* unsigned no_port:1 */
|
||||
ngx_str_t host;
|
||||
in_port_t port;
|
||||
ngx_uint_t no_port; /* unsigned no_port:1 */
|
||||
|
||||
ngx_uint_t naddrs;
|
||||
in_addr_t *addrs;
|
||||
ngx_uint_t naddrs;
|
||||
in_addr_t *addrs;
|
||||
|
||||
struct sockaddr *sockaddr;
|
||||
socklen_t socklen;
|
||||
struct sockaddr *sockaddr;
|
||||
socklen_t socklen;
|
||||
|
||||
ngx_resolver_ctx_t *ctx;
|
||||
ngx_resolver_ctx_t *ctx;
|
||||
} ngx_http_upstream_resolved_t;
|
||||
|
||||
|
||||
@ -225,63 +233,69 @@ typedef void (*ngx_http_upstream_handler_pt)(ngx_http_request_t *r,
|
||||
|
||||
|
||||
struct ngx_http_upstream_s {
|
||||
ngx_http_upstream_handler_pt read_event_handler;
|
||||
ngx_http_upstream_handler_pt write_event_handler;
|
||||
ngx_http_upstream_handler_pt read_event_handler;
|
||||
ngx_http_upstream_handler_pt write_event_handler;
|
||||
|
||||
ngx_peer_connection_t peer;
|
||||
ngx_peer_connection_t peer;
|
||||
|
||||
ngx_event_pipe_t *pipe;
|
||||
ngx_event_pipe_t *pipe;
|
||||
|
||||
ngx_chain_t *request_bufs;
|
||||
ngx_chain_t *request_bufs;
|
||||
|
||||
ngx_output_chain_ctx_t output;
|
||||
ngx_chain_writer_ctx_t writer;
|
||||
ngx_output_chain_ctx_t output;
|
||||
ngx_chain_writer_ctx_t writer;
|
||||
|
||||
ngx_http_upstream_conf_t *conf;
|
||||
ngx_http_upstream_conf_t *conf;
|
||||
|
||||
ngx_http_upstream_headers_in_t headers_in;
|
||||
ngx_http_upstream_headers_in_t headers_in;
|
||||
|
||||
ngx_http_upstream_resolved_t *resolved;
|
||||
ngx_http_upstream_resolved_t *resolved;
|
||||
|
||||
ngx_buf_t buffer;
|
||||
size_t length;
|
||||
ngx_buf_t buffer;
|
||||
size_t length;
|
||||
|
||||
ngx_chain_t *out_bufs;
|
||||
ngx_chain_t *busy_bufs;
|
||||
ngx_chain_t *free_bufs;
|
||||
ngx_chain_t *out_bufs;
|
||||
ngx_chain_t *busy_bufs;
|
||||
ngx_chain_t *free_bufs;
|
||||
|
||||
ngx_int_t (*input_filter_init)(void *data);
|
||||
ngx_int_t (*input_filter)(void *data, ssize_t bytes);
|
||||
void *input_filter_ctx;
|
||||
ngx_int_t (*input_filter_init)(void *data);
|
||||
ngx_int_t (*input_filter)(void *data, ssize_t bytes);
|
||||
void *input_filter_ctx;
|
||||
|
||||
ngx_int_t (*create_request)(ngx_http_request_t *r);
|
||||
ngx_int_t (*reinit_request)(ngx_http_request_t *r);
|
||||
ngx_int_t (*process_header)(ngx_http_request_t *r);
|
||||
void (*abort_request)(ngx_http_request_t *r);
|
||||
void (*finalize_request)(ngx_http_request_t *r,
|
||||
ngx_int_t rc);
|
||||
ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, size_t prefix);
|
||||
#if (NGX_HTTP_CACHE)
|
||||
ngx_int_t (*create_key)(ngx_http_request_t *r);
|
||||
#endif
|
||||
ngx_int_t (*create_request)(ngx_http_request_t *r);
|
||||
ngx_int_t (*reinit_request)(ngx_http_request_t *r);
|
||||
ngx_int_t (*process_header)(ngx_http_request_t *r);
|
||||
void (*abort_request)(ngx_http_request_t *r);
|
||||
void (*finalize_request)(ngx_http_request_t *r,
|
||||
ngx_int_t rc);
|
||||
ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r,
|
||||
ngx_table_elt_t *h, size_t prefix);
|
||||
|
||||
ngx_msec_t timeout;
|
||||
ngx_msec_t timeout;
|
||||
|
||||
ngx_http_upstream_state_t *state;
|
||||
ngx_http_upstream_state_t *state;
|
||||
|
||||
ngx_str_t method;
|
||||
ngx_str_t schema;
|
||||
ngx_str_t uri;
|
||||
ngx_str_t method;
|
||||
ngx_str_t schema;
|
||||
ngx_str_t uri;
|
||||
|
||||
ngx_http_cleanup_pt *cleanup;
|
||||
ngx_http_cleanup_pt *cleanup;
|
||||
|
||||
unsigned store:1;
|
||||
unsigned cacheable:1;
|
||||
unsigned accel:1;
|
||||
unsigned ssl:1;
|
||||
unsigned store:1;
|
||||
unsigned cacheable:1;
|
||||
unsigned accel:1;
|
||||
unsigned ssl:1;
|
||||
#if (NGX_HTTP_CACHE)
|
||||
unsigned stale_cache:1;
|
||||
#endif
|
||||
|
||||
unsigned buffering:1;
|
||||
unsigned buffering:1;
|
||||
|
||||
unsigned request_sent:1;
|
||||
unsigned header_sent:1;
|
||||
unsigned request_sent:1;
|
||||
unsigned header_sent:1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -67,6 +67,7 @@ typedef struct {
|
||||
#define NGX_FILE_APPEND O_APPEND
|
||||
|
||||
#define NGX_FILE_DEFAULT_ACCESS 0644
|
||||
#define NGX_FILE_OWNER_ACCESS 0600
|
||||
|
||||
|
||||
#define ngx_close_file close
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
|
||||
ngx_int_t type);
|
||||
static void ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type);
|
||||
static void ngx_start_cleaner_process(ngx_cycle_t *cycle, ngx_int_t type);
|
||||
static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
|
||||
static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
|
||||
static void ngx_master_process_exit(ngx_cycle_t *cycle);
|
||||
@ -24,9 +24,8 @@ static void ngx_channel_handler(ngx_event_t *ev);
|
||||
static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle);
|
||||
static ngx_thread_value_t ngx_worker_thread_cycle(void *data);
|
||||
#endif
|
||||
#if 0
|
||||
static void ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data);
|
||||
#endif
|
||||
static void ngx_cleaner_process_cycle(ngx_cycle_t *cycle, void *data);
|
||||
static void ngx_cleaner_process_handler(ngx_event_t *ev);
|
||||
|
||||
|
||||
ngx_uint_t ngx_process;
|
||||
@ -123,7 +122,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
|
||||
|
||||
ngx_start_worker_processes(cycle, ccf->worker_processes,
|
||||
NGX_PROCESS_RESPAWN);
|
||||
ngx_start_garbage_collector(cycle, NGX_PROCESS_RESPAWN);
|
||||
ngx_start_cleaner_process(cycle, NGX_PROCESS_RESPAWN);
|
||||
|
||||
ngx_new_binary = 0;
|
||||
delay = 0;
|
||||
@ -204,7 +203,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
|
||||
if (ngx_new_binary) {
|
||||
ngx_start_worker_processes(cycle, ccf->worker_processes,
|
||||
NGX_PROCESS_RESPAWN);
|
||||
ngx_start_garbage_collector(cycle, NGX_PROCESS_RESPAWN);
|
||||
ngx_start_cleaner_process(cycle, NGX_PROCESS_RESPAWN);
|
||||
ngx_noaccepting = 0;
|
||||
|
||||
continue;
|
||||
@ -223,7 +222,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
|
||||
ngx_core_module);
|
||||
ngx_start_worker_processes(cycle, ccf->worker_processes,
|
||||
NGX_PROCESS_JUST_RESPAWN);
|
||||
ngx_start_garbage_collector(cycle, NGX_PROCESS_JUST_RESPAWN);
|
||||
ngx_start_cleaner_process(cycle, NGX_PROCESS_JUST_RESPAWN);
|
||||
live = 1;
|
||||
ngx_signal_worker_processes(cycle,
|
||||
ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
|
||||
@ -233,7 +232,7 @@ ngx_master_process_cycle(ngx_cycle_t *cycle)
|
||||
ngx_restart = 0;
|
||||
ngx_start_worker_processes(cycle, ccf->worker_processes,
|
||||
NGX_PROCESS_RESPAWN);
|
||||
ngx_start_garbage_collector(cycle, NGX_PROCESS_RESPAWN);
|
||||
ngx_start_cleaner_process(cycle, NGX_PROCESS_RESPAWN);
|
||||
live = 1;
|
||||
}
|
||||
|
||||
@ -361,18 +360,28 @@ ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
|
||||
|
||||
|
||||
static void
|
||||
ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type)
|
||||
ngx_start_cleaner_process(ngx_cycle_t *cycle, ngx_int_t type)
|
||||
{
|
||||
#if 0
|
||||
ngx_int_t i;
|
||||
ngx_channel_t ch;
|
||||
ngx_int_t i;
|
||||
ngx_uint_t n;
|
||||
ngx_path_t **path;
|
||||
ngx_channel_t ch;
|
||||
|
||||
ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start garbage collector");
|
||||
path = ngx_cycle->pathes.elts;
|
||||
for (n = 0; n < ngx_cycle->pathes.nelts; n++) {
|
||||
if (path[n]->cleaner) {
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
start:
|
||||
|
||||
ch.command = NGX_CMD_OPEN_CHANNEL;
|
||||
|
||||
ngx_spawn_process(cycle, ngx_garbage_collector_cycle, NULL,
|
||||
"garbage collector", type);
|
||||
ngx_spawn_process(cycle, ngx_cleaner_process_cycle, NULL,
|
||||
"cleaner process", type);
|
||||
|
||||
ch.pid = ngx_processes[ngx_process_slot].pid;
|
||||
ch.slot = ngx_process_slot;
|
||||
@ -398,7 +407,6 @@ ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type)
|
||||
ngx_write_channel(ngx_processes[i].channel[0],
|
||||
&ch, sizeof(ngx_channel_t), cycle->log);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1254,27 +1262,29 @@ ngx_worker_thread_cycle(void *data)
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static void
|
||||
ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data)
|
||||
ngx_cleaner_process_cycle(ngx_cycle_t *cycle, void *data)
|
||||
{
|
||||
ngx_uint_t i;
|
||||
ngx_gc_t ctx;
|
||||
ngx_path_t **path;
|
||||
ngx_event_t *ev;
|
||||
void *ident[4];
|
||||
ngx_event_t ev;
|
||||
|
||||
cycle->connection_n = 512;
|
||||
|
||||
ngx_worker_process_init(cycle, 0);
|
||||
|
||||
ev = &cycle->read_events0[ngx_channel];
|
||||
ngx_close_listening_sockets(cycle);
|
||||
|
||||
ngx_accept_mutex = NULL;
|
||||
ngx_memzero(&ev, sizeof(ngx_event_t));
|
||||
ev.handler = ngx_cleaner_process_handler;
|
||||
ev.data = ident;
|
||||
ev.log = cycle->log;
|
||||
ident[3] = (void *) -1;
|
||||
|
||||
ngx_setproctitle("garbage collector");
|
||||
ngx_use_accept_mutex = 0;
|
||||
|
||||
#if 0
|
||||
ngx_add_timer(ev, 60 * 1000);
|
||||
#endif
|
||||
ngx_setproctitle("cleaner process");
|
||||
|
||||
ngx_add_timer(&ev, 0);
|
||||
|
||||
for ( ;; ) {
|
||||
|
||||
@ -1289,19 +1299,35 @@ ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data)
|
||||
ngx_reopen_files(cycle, -1);
|
||||
}
|
||||
|
||||
path = cycle->pathes.elts;
|
||||
for (i = 0; i < cycle->pathes.nelts; i++) {
|
||||
ctx.path = path[i];
|
||||
ctx.log = cycle->log;
|
||||
ctx.handler = path[i]->cleaner;
|
||||
|
||||
ngx_collect_garbage(&ctx, &path[i]->name, 0);
|
||||
}
|
||||
|
||||
ngx_add_timer(ev, 60 * 60 * 1000);
|
||||
|
||||
ngx_process_events_and_timers(cycle);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
ngx_cleaner_process_handler(ngx_event_t *ev)
|
||||
{
|
||||
time_t next, n;
|
||||
ngx_uint_t i;
|
||||
ngx_path_t **path;
|
||||
|
||||
next = 60 * 60;
|
||||
|
||||
path = ngx_cycle->pathes.elts;
|
||||
for (i = 0; i < ngx_cycle->pathes.nelts; i++) {
|
||||
|
||||
if (path[i]->cleaner) {
|
||||
n = path[i]->cleaner(path[i]->data);
|
||||
|
||||
next = (n <= next) ? n : next;
|
||||
|
||||
ngx_time_update(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (next == 0) {
|
||||
next = 1;
|
||||
}
|
||||
|
||||
ngx_add_timer(ev, next * 1000);
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ typedef struct {
|
||||
#define NGX_FILE_APPEND 0
|
||||
|
||||
#define NGX_FILE_DEFAULT_ACCESS 0
|
||||
#define NGX_FILE_OWNER_ACCESS 0
|
||||
|
||||
|
||||
ngx_int_t ngx_file_append_mode(ngx_fd_t fd);
|
||||
|
Loading…
Reference in New Issue
Block a user