📄 ngx_http_upstream.c
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_http.h>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);static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r, ngx_event_t *ev);static void ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u);static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u);static void ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u);static void ngx_http_upstream_send_request_handler(ngx_event_t *wev);static void ngx_http_upstream_process_header(ngx_event_t *rev);static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);static void ngx_http_upstream_process_body_in_memory(ngx_event_t *rev);static void ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u);static void ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);static void ngx_http_upstream_process_non_buffered_body(ngx_event_t *ev);static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);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);static void ngx_http_upstream_cleanup(void *data);static void ngx_http_upstream_finalize_request(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_int_t rc);static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);static ngx_int_t ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);static ngx_int_t ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset);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_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);#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);#endifstatic ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);#if (NGX_HTTP_SSL)static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, ngx_http_upstream_t *u, ngx_connection_t *c);static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);#endifngx_http_upstream_header_t ngx_http_upstream_headers_in[] = { { ngx_string("Status"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, status), ngx_http_upstream_copy_header_line, 0, 0 }, { ngx_string("Content-Type"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, content_type), ngx_http_upstream_copy_content_type, 0, 1 }, { ngx_string("Content-Length"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, content_length), ngx_http_upstream_copy_content_length, 0, 0 }, { ngx_string("Date"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, date), 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), ngx_http_upstream_copy_header_line, offsetof(ngx_http_headers_out_t, server), 0 }, { ngx_string("WWW-Authenticate"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, www_authenticate), ngx_http_upstream_copy_header_line, 0, 0 }, { ngx_string("Location"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_rewrite_location, 0, 0 }, { ngx_string("Refresh"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_rewrite_refresh, 0, 0 }, { ngx_string("Set-Cookie"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_copy_header_line, 0, 1 }, { ngx_string("Content-Disposition"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_copy_header_line, 0, 1 }, { ngx_string("Cache-Control"), ngx_http_upstream_process_multi_header_lines, offsetof(ngx_http_upstream_headers_in_t, cache_control), ngx_http_upstream_copy_multi_header_lines, offsetof(ngx_http_headers_out_t, cache_control), 1 }, { ngx_string("Expires"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, expires), ngx_http_upstream_copy_header_line, offsetof(ngx_http_headers_out_t, expires), 1 }, { 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, offsetof(ngx_http_headers_out_t, accept_ranges), 1 }, { ngx_string("Connection"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("Keep-Alive"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("X-Powered-By"), ngx_http_upstream_ignore_header_line, 0, ngx_http_upstream_copy_header_line, 0, 0 }, { ngx_string("X-Accel-Expires"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, x_accel_expires), ngx_http_upstream_copy_header_line, 0, 0 }, { ngx_string("X-Accel-Redirect"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect), ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("X-Accel-Limit-Rate"), ngx_http_upstream_process_limit_rate, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("X-Accel-Buffering"), ngx_http_upstream_process_buffering, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, { ngx_string("X-Accel-Charset"), ngx_http_upstream_process_charset, 0, ngx_http_upstream_ignore_header_line, 0, 0 },#if (NGX_HTTP_GZIP) { ngx_string("Content-Encoding"), ngx_http_upstream_process_header_line, offsetof(ngx_http_upstream_headers_in_t, content_encoding), ngx_http_upstream_copy_content_encoding, 0, 0 },#endif { ngx_null_string, NULL, 0, NULL, 0, 0 }};static ngx_command_t ngx_http_upstream_commands[] = { { ngx_string("upstream"), NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1, ngx_http_upstream, 0, 0, NULL }, { ngx_string("server"), NGX_HTTP_UPS_CONF|NGX_CONF_1MORE, ngx_http_upstream_server, NGX_HTTP_SRV_CONF_OFFSET, 0, NULL }, ngx_null_command};static ngx_http_module_t ngx_http_upstream_module_ctx = { ngx_http_upstream_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ ngx_http_upstream_create_main_conf, /* create main configuration */ ngx_http_upstream_init_main_conf, /* init main configuration */ NULL, /* create server configuration */ NULL, /* merge server configuration */ NULL, /* create location configuration */ NULL /* merge location configuration */};ngx_module_t ngx_http_upstream_module = { NGX_MODULE_V1, &ngx_http_upstream_module_ctx, /* module context */ ngx_http_upstream_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING};static ngx_http_variable_t ngx_http_upstream_vars[] = { { ngx_string("upstream_addr"), NULL, ngx_http_upstream_addr_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("upstream_status"), NULL, ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, { ngx_string("upstream_response_time"), NULL, ngx_http_upstream_response_time_variable, 0, NGX_HTTP_VAR_NOHASH, 0 }, { ngx_null_string, NULL, NULL, 0, 0, 0 }};voidngx_http_upstream_init(ngx_http_request_t *r){ ngx_str_t *host; ngx_uint_t i; ngx_connection_t *c; ngx_resolver_ctx_t *ctx, temp; ngx_http_cleanup_t *cln; ngx_http_upstream_t *u; ngx_http_core_loc_conf_t *clcf; ngx_http_upstream_srv_conf_t *uscf, **uscfp; ngx_http_upstream_main_conf_t *umcf; c = r->connection; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http init upstream, client timer: %d", c->read->timer_set); if (c->read->timer_set) { ngx_del_timer(c->read); } u = r->upstream; if (!r->post_action && !u->conf->ignore_client_abort) { r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; r->write_event_handler = ngx_http_upstream_wr_check_broken_connection; } if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { if (!c->write->active) { if (ngx_add_event(c->write, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } } } if (r->request_body) { u->request_bufs = r->request_body->bufs; } if (u->create_request(r) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); u->output.pool = r->pool; u->output.bufs.num = 1; u->output.bufs.size = clcf->client_body_buffer_size; u->output.output_filter = ngx_chain_writer; u->output.filter_ctx = &u->writer; u->writer.pool = r->pool; if (r->upstream_states == NULL) { r->upstream_states = ngx_array_create(r->pool, 1, sizeof(ngx_http_upstream_state_t)); if (r->upstream_states == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } } else { u->state = ngx_array_push(r->upstream_states); if (u->state == NULL) { ngx_http_upstream_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); } cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } cln->handler = ngx_http_upstream_cleanup; cln->data = r; u->cleanup = &cln->handler; u->store = (u->conf->store || u->conf->store_lengths); if (u->resolved == NULL) { uscf = u->conf->upstream; } else { host = &u->resolved->host; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; if (uscf->host.len == host->len && ((uscf->port == 0 && u->resolved->default_port) || uscf->port == u->resolved->port) && ngx_memcmp(uscf->host.data, host->data, host->len) == 0) { goto found; } } temp.name = *host; ctx = ngx_resolve_start(clcf->resolver, &temp); if (ctx == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } if (ctx == NGX_NO_RESOLVER) { ngx_log_error(NGX_LOG_ERR, c->log, 0, "no resolver defined to resolve %V", host); ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY); return; } ctx->name = *host; ctx->type = NGX_RESOLVE_A; ctx->handler = ngx_http_upstream_resolve_handler; ctx->data = r; ctx->timeout = clcf->resolver_timeout; u->resolved->ctx = ctx; if (ngx_resolve_name(ctx) != NGX_OK) { u->resolved->ctx = NULL; ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } return; }found: if (uscf->peer.init(r, uscf) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_http_upstream_connect(r, u);}static voidngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx){ ngx_http_request_t *r; ngx_http_upstream_resolved_t *ur; r = ctx->data; r->upstream->resolved->ctx = NULL; if (ctx->state) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V could not be resolved (%i: %s)", &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -