mirror of
https://github.com/nginx/nginx.git
synced 2024-12-27 01:11:13 -06:00
proxy_store and fastcgi_store
This commit is contained in:
parent
ef6e362d4e
commit
58feb53eb4
@ -293,6 +293,72 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||
{
|
||||
char *confp = conf;
|
||||
|
||||
u_char *p;
|
||||
ngx_str_t *value;
|
||||
ngx_uint_t i, right, shift, *access;
|
||||
|
||||
access = (ngx_uint_t *) (confp + cmd->offset);
|
||||
|
||||
if (*access != NGX_CONF_UNSET_UINT) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
|
||||
*access = 0600;
|
||||
|
||||
for (i = 1; i < cf->args->nelts; i++) {
|
||||
|
||||
p = value[i].data;
|
||||
|
||||
if (ngx_strncmp(p, "user:", sizeof("user:") - 1) == 0) {
|
||||
shift = 6;
|
||||
p += sizeof("user:") - 1;
|
||||
|
||||
} else if (ngx_strncmp(p, "group:", sizeof("group:") - 1) == 0) {
|
||||
shift = 3;
|
||||
p += sizeof("group:") - 1;
|
||||
|
||||
} else if (ngx_strncmp(p, "all:", sizeof("all:") - 1) == 0) {
|
||||
shift = 0;
|
||||
p += sizeof("all:") - 1;
|
||||
|
||||
} else if (ngx_strncmp(p, "off", sizeof("off") - 1) == 0) {
|
||||
*access = 0;
|
||||
return NGX_CONF_OK;
|
||||
|
||||
} else {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
if (ngx_strcmp(p, "rw") == 0) {
|
||||
right = 6;
|
||||
|
||||
} else if (ngx_strcmp(p, "r") == 0) {
|
||||
right = 4;
|
||||
|
||||
} else {
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
*access |= right << shift;
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
|
||||
invalid:
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid value \"%V\"", &value[i]);
|
||||
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot)
|
||||
{
|
||||
|
@ -95,6 +95,7 @@ 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_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) \
|
||||
|
@ -200,6 +200,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
|
||||
offsetof(ngx_http_fastcgi_loc_conf_t, index),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("fastcgi_store"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
|
||||
ngx_conf_set_access_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.store),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("fastcgi_ignore_client_abort"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
@ -1633,6 +1640,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
|
||||
* conf->index.data = NULL;
|
||||
*/
|
||||
|
||||
conf->upstream.store = NGX_CONF_UNSET_UINT;
|
||||
conf->upstream.buffering = NGX_CONF_UNSET;
|
||||
conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
|
||||
|
||||
@ -1677,6 +1685,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_http_script_copy_code_t *copy;
|
||||
|
||||
ngx_conf_merge_uint_value(conf->upstream.store,
|
||||
prev->upstream.store, 0);
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.buffering,
|
||||
prev->upstream.buffering, 1);
|
||||
|
||||
|
@ -154,6 +154,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
|
||||
0,
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_store"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
|
||||
ngx_conf_set_access_slot,
|
||||
NGX_HTTP_LOC_CONF_OFFSET,
|
||||
offsetof(ngx_http_proxy_loc_conf_t, upstream.store),
|
||||
NULL },
|
||||
|
||||
{ ngx_string("proxy_buffering"),
|
||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||
ngx_conf_set_flag_slot,
|
||||
@ -1502,6 +1509,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
|
||||
* conf->rewrite_locations = NULL;
|
||||
*/
|
||||
|
||||
conf->upstream.store = NGX_CONF_UNSET_UINT;
|
||||
conf->upstream.buffering = NGX_CONF_UNSET;
|
||||
conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
|
||||
|
||||
@ -1553,6 +1561,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_http_script_copy_code_t *copy;
|
||||
|
||||
ngx_conf_merge_uint_value(conf->upstream.store,
|
||||
prev->upstream.store, 0);
|
||||
|
||||
ngx_conf_merge_value(conf->upstream.buffering,
|
||||
prev->upstream.buffering, 1);
|
||||
|
||||
|
@ -33,6 +33,8 @@ static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
|
||||
ssize_t bytes);
|
||||
static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
|
||||
static void ngx_http_upstream_process_body(ngx_event_t *ev);
|
||||
static void ngx_http_upstream_store(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u);
|
||||
static void ngx_http_upstream_dummy_handler(ngx_event_t *wev);
|
||||
static void ngx_http_upstream_next(ngx_http_request_t *r,
|
||||
ngx_http_upstream_t *u, ngx_uint_t ft_type);
|
||||
@ -116,6 +118,12 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
|
||||
ngx_http_upstream_copy_header_line,
|
||||
offsetof(ngx_http_headers_out_t, date), 0 },
|
||||
|
||||
{ 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_string("Server"),
|
||||
ngx_http_upstream_process_header_line,
|
||||
offsetof(ngx_http_upstream_headers_in_t, server),
|
||||
@ -364,6 +372,8 @@ ngx_http_upstream_init(ngx_http_request_t *r)
|
||||
cln->data = r;
|
||||
u->cleanup = &cln->handler;
|
||||
|
||||
u->store = (u->conf->store != 0);
|
||||
|
||||
ngx_http_upstream_connect(r, u);
|
||||
}
|
||||
|
||||
@ -424,7 +434,7 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
|
||||
ev->error = 1;
|
||||
}
|
||||
|
||||
if (!u->cachable && u->peer.connection) {
|
||||
if (!u->cachable && !u->store && u->peer.connection) {
|
||||
ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
|
||||
"kevent() reported that client closed prematurely "
|
||||
"connection, so upstream connection is closed too");
|
||||
@ -490,7 +500,7 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
|
||||
ev->eof = 1;
|
||||
c->error = 1;
|
||||
|
||||
if (!u->cachable && u->peer.connection) {
|
||||
if (!u->cachable && !u->store && u->peer.connection) {
|
||||
ngx_log_error(NGX_LOG_INFO, ev->log, err,
|
||||
"client closed prematurely connection, "
|
||||
"so upstream connection is closed too");
|
||||
@ -1523,7 +1533,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
p->pool = r->pool;
|
||||
p->log = c->log;
|
||||
|
||||
p->cachable = u->cachable;
|
||||
p->cachable = u->cachable || u->store;
|
||||
|
||||
p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
|
||||
if (p->temp_file == NULL) {
|
||||
@ -1536,8 +1546,9 @@ 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->cachable) {
|
||||
if (u->cachable || u->store) {
|
||||
p->temp_file->persistent = 1;
|
||||
|
||||
} else {
|
||||
p->temp_file->log_level = NGX_LOG_WARN;
|
||||
p->temp_file->warn = "an upstream response is buffered "
|
||||
@ -1552,6 +1563,7 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
ngx_http_upstream_finalize_request(r, u, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
p->preread_bufs->buf = &u->buffer;
|
||||
p->preread_bufs->next = NULL;
|
||||
u->buffer.recycled = 1;
|
||||
@ -1559,11 +1571,13 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
p->preread_size = u->buffer.last - u->buffer.pos;
|
||||
|
||||
if (u->cachable) {
|
||||
|
||||
p->buf_to_file = ngx_calloc_buf(r->pool);
|
||||
if (p->buf_to_file == NULL) {
|
||||
ngx_http_upstream_finalize_request(r, u, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
p->buf_to_file->pos = u->buffer.start;
|
||||
p->buf_to_file->last = u->buffer.pos;
|
||||
p->buf_to_file->temporary = 1;
|
||||
@ -1910,6 +1924,27 @@ ngx_http_upstream_process_body(ngx_event_t *ev)
|
||||
|
||||
if (u->peer.connection) {
|
||||
|
||||
if (u->store) {
|
||||
|
||||
if (p->upstream_eof && u->headers_in.status_n == NGX_HTTP_OK) {
|
||||
|
||||
ngx_http_upstream_store(r, u);
|
||||
|
||||
} else if ((p->upstream_error
|
||||
|| (p->upstream_eof
|
||||
&& u->headers_in.status_n != NGX_HTTP_OK))
|
||||
&& u->pipe->temp_file->file.fd != NGX_INVALID_FILE)
|
||||
{
|
||||
if (ngx_delete_file(u->pipe->temp_file->file.name.data)
|
||||
== NGX_FILE_ERROR)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
|
||||
ngx_delete_file_n " \"%s\" failed",
|
||||
u->pipe->temp_file->file.name.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_FILE_CACHE)
|
||||
|
||||
if (p->upstream_done && u->cachable) {
|
||||
@ -1954,6 +1989,130 @@ ngx_http_upstream_process_body(ngx_event_t *ev)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
|
||||
{
|
||||
char *failed;
|
||||
u_char *name;
|
||||
size_t root;
|
||||
time_t lm;
|
||||
ngx_err_t err;
|
||||
ngx_str_t *temp, path, *last_modified;
|
||||
ngx_temp_file_t *tf;
|
||||
|
||||
if (u->pipe->temp_file->file.fd == NGX_INVALID_FILE) {
|
||||
|
||||
/* create file for empty 200 response */
|
||||
|
||||
tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
|
||||
if (tf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
tf->file.fd = NGX_INVALID_FILE;
|
||||
tf->file.log = r->connection->log;
|
||||
tf->path = u->conf->temp_path;
|
||||
tf->pool = r->pool;
|
||||
tf->persistent = 1;
|
||||
|
||||
if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
|
||||
tf->persistent, tf->clean, tf->access)
|
||||
!= NGX_OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
u->pipe->temp_file = tf;
|
||||
}
|
||||
|
||||
temp = &u->pipe->temp_file->file.name;
|
||||
|
||||
#if !(NGX_WIN32)
|
||||
|
||||
if (ngx_change_file_access(temp->data, u->conf->store) == NGX_FILE_ERROR) {
|
||||
err = ngx_errno;
|
||||
failed = ngx_change_file_access_n;
|
||||
name = temp->data;
|
||||
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (r->upstream->headers_in.last_modified) {
|
||||
|
||||
last_modified = &r->upstream->headers_in.last_modified->value;
|
||||
|
||||
lm = ngx_http_parse_time(last_modified->data, last_modified->len);
|
||||
|
||||
if (lm != NGX_ERROR) {
|
||||
if (ngx_set_file_time(temp->data, u->pipe->temp_file->file.fd, lm)
|
||||
!= NGX_OK)
|
||||
{
|
||||
err = ngx_errno;
|
||||
failed = ngx_set_file_time_n;
|
||||
name = temp->data;
|
||||
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngx_http_map_uri_to_path(r, &path, &root, 0);
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"upstream stores \"%s\" to \"%s\"", temp->data, path.data);
|
||||
|
||||
failed = ngx_rename_file_n;
|
||||
name = path.data;
|
||||
|
||||
if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = ngx_errno;
|
||||
|
||||
if (err == NGX_ENOENT) {
|
||||
|
||||
err = ngx_create_full_path(path.data, ngx_dir_access(u->conf->store));
|
||||
|
||||
if (err == 0) {
|
||||
if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = ngx_errno;
|
||||
}
|
||||
}
|
||||
|
||||
#if (NGX_WIN32)
|
||||
|
||||
if (err == NGX_EEXIST) {
|
||||
if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) {
|
||||
|
||||
if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
err = ngx_errno;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
failed:
|
||||
|
||||
if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
|
||||
ngx_delete_file_n " \"%s\" failed",
|
||||
temp->data);
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
|
||||
"%s \"%s\" failed", failed, name);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ngx_http_upstream_dummy_handler(ngx_event_t *wev)
|
||||
{
|
||||
|
@ -118,6 +118,7 @@ typedef struct {
|
||||
size_t temp_file_write_size_conf;
|
||||
|
||||
ngx_uint_t next_upstream;
|
||||
ngx_uint_t store;
|
||||
|
||||
ngx_bufs_t bufs;
|
||||
|
||||
@ -237,6 +238,7 @@ struct ngx_http_upstream_s {
|
||||
|
||||
ngx_http_cleanup_pt *cleanup;
|
||||
|
||||
unsigned store:1;
|
||||
unsigned cachable:1;
|
||||
unsigned accel:1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user