static void
ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
...
rc = ngx_http_send_header(r); //发送头部数据到请求端
if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) { //满足条件 由ngx_http_upstream_finalize_request处理
ngx_http_upstream_finalize_request(r, u, rc);
return;
}
u->header_sent = 1; //标记头部发送
if (u->upgrade) { //upgrage升级处理
ngx_http_upstream_upgrade(r, u);
return;
}
c = r->connection;
if (r->header_only) { //只有请求头
if (!u->buffering) { //不进行缓冲
ngx_http_upstream_finalize_request(r, u, rc);
return;
}
if (!u->cacheable && !u->store) { //不可缓存 并且不保存
ngx_http_upstream_finalize_request(r, u, rc);
return;
}
u->pipe->downstream_error = 1; //只有请求头部 便标记为downstream_error
}
if (r->request_body && r->request_body->temp_file) { //对在临时文件的请求包体进行清理
ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->);
r->request_body->temp_file-> = NGX_INVALID_FILE;
}
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (!u->buffering) { //不进行缓冲处理
if (u->input_filter == NULL) {
u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
u->input_filter = ngx_http_upstream_non_buffered_filter;
u->input_filter_ctx = r;
}
u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
r->write_event_handler =
ngx_http_upstream_process_non_buffered_downstream;
r->limit_rate = 0;
if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { //设置tcp_nodelay
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
tcp_nodelay = 1;
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
(const void *) &tcp_nodelay, sizeof(int)) == -1)
{
ngx_connection_error(c, ngx_socket_errno,
"setsockopt(TCP_NODELAY) failed");
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
c->tcp_nodelay = NGX_TCP_NODELAY_SET;
}
n = u-> - u->;
if (n) {
u-> = u->;
u->state->response_length += n;
if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
ngx_http_upstream_process_non_buffered_downstream(r);
} else {
u-> = u->;
u-> = u->;
if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
if (u->->read->ready || u->length == 0) {
ngx_http_upstream_process_non_buffered_upstream(r, u);
}
}
return;
}
/* TODO: preallocate event_pipe bufs, look "Content-Length" */
if (r->cache && r->cache-> != NGX_INVALID_FILE) { //缓存文件无效 进行文件清理
ngx_pool_run_cleanup_file(r->pool, r->cache->);
r->cache-> = NGX_INVALID_FILE;
}
switch (ngx_http_test_predicates(r, u->conf->no_cache)) { //no_cache检测
case NGX_ERROR:
ngx_http_upstream_finalize_request(r, u, NGX_ERROR); //检测出错
return;
case NGX_DECLINED: //满足不缓存条件 设置不缓存标记
u->cacheable = 0;
break;
default: /* NGX_OK */
if (u->cache_status == NGX_HTTP_CACHE_BYPASS) { //可以进行缓存
/* create cache if previously bypassed */
if (ngx_http_file_cache_create(r) != NGX_OK) { //创建缓存文件
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
}
break;
}
if (u->cacheable) {
time_t now, valid;
now = ngx_time();
valid = r->cache->valid_sec;
if (valid == 0) {
valid = ngx_http_file_cache_valid(u->conf->cache_valid,
u->headers_in.status_n); //获取缓存有效期
if (valid) {
r->cache->valid_sec = now + valid; //更新缓存有效期
}
}
if (valid) {
r->cache->date = now;
r->cache->body_start = (u_short) (u-> - u->); //body_start位置获取
if (u->headers_in.status_n == NGX_HTTP_OK
|| u->headers_in.status_n == NGX_HTTP_PARTIAL_CONTENT) //缓存满足200/206状态值 必要参数更新
{
r->cache->last_modified = u->headers_in.last_modified_time; //更新缓存的last_modified_time值
if (u->headers_in.etag) { //更新缓存的etag值
r->cache->etag = u->headers_in.etag->value;
} else {
ngx_str_null(&r->cache->etag); //etag赋空值
}
} else {
r->cache->last_modified = -1;
ngx_str_null(&r->cache->etag);
}
if (ngx_http_file_cache_set_header(r, u->) != NGX_OK) { //设置缓存头部信息
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
} else { //无valid_sec 即没有有效时间 不可缓存
u->cacheable = 0;
}
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http cacheable: %d", u->cacheable);
if (u->cacheable == 0 && r->cache) { //临时文件清理
ngx_http_file_cache_free(r, u->pipe->temp_file);
}
if (r->header_only && !u->cacheable && !u->store) { //满足只有head请求或者body数据返回条件
ngx_http_upstream_finalize_request(r, u, 0);
return;
}
p = u->pipe;
p->output_filter = ngx_http_upstream_output_filter; //event_pipe对响应请求包体处理
p->output_ctx = r;
p->tag = u->;
p->bufs = u->conf->bufs;
p->busy_size = u->conf->busy_buffers_size;
p->upstream = u->;
p->downstream = c;
p->pool = r->pool;
p->log = c->log;
p->limit_rate = u->conf->limit_rate;
p->start_sec = ngx_time();
p->cacheable = u->cacheable || u->store; //传入upstream标记值
p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); //创建临时文件 以用于缓存包体信息
if (p->temp_file == NULL) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
p->temp_file-> = NGX_INVALID_FILE;
p->temp_file-> = c->log;
p->temp_file->path = u->conf->temp_path;
p->temp_file->pool = r->pool;
if (p->cacheable) {
p->temp_file->persistent = 1; //临时文件不会在close调用之后进行销毁
if (r->cache && r->cache->file_cache->temp_path) {
p->temp_file->path = r->cache->file_cache->temp_path; //传入临时文件目录
}
} else {
p->temp_file->log_level = NGX_LOG_WARN;
p->temp_file->warn = "an upstream response is buffered "
"to a temporary file";
}
p->max_temp_file_size = u->conf->max_temp_file_size; //传入临时文件配置的大小限制
p->temp_file_write_size = u->conf->temp_file_write_size;
if (clcf->aio == NGX_HTTP_AIO_THREADS && clcf->aio_write) { //任务提交到线程池
p->thread_handler = ngx_http_upstream_thread_handler;
p->thread_ctx = r;
}
p->preread_bufs = ngx_alloc_chain_link(r->pool);
if (p->preread_bufs == NULL) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
p->preread_bufs->buf = &u->buffer;
p->preread_bufs->next = NULL;
u-> = 1;
p->preread_size = u-> - u->;
if (u->cacheable) {
p->buf_to_file = ngx_calloc_buf(r->pool); //创建写入到文件的buffer缓冲
if (p->buf_to_file == NULL) {
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
p->buf_to_file->start = u->;
p->buf_to_file->pos = u->;
p->buf_to_file->last = u->;
p->buf_to_file->temporary = 1;
}
if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
/* the posted aio operation may corrupt a shadow buffer */
p->single_buf = 1;
}
/* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
p->free_bufs = 1;
/*
* event_pipe would do u-> += p->preread_size
* as though these bytes were read
*/
u-> = u->;
if (u->conf->cyclic_temp_file) { //临时文件复用标记
/*
* we need to disable the use of sendfile() if we use cyclic temp file
* because the writing a new data may interfere with sendfile()
* that uses the same kernel file pages (at least on FreeBSD)
*/
p->cyclic_temp_file = 1;
c->sendfile = 0;
} else {
p->cyclic_temp_file = 0;
}
p->read_timeout = u->conf->read_timeout;
p->send_timeout = clcf->send_timeout;
p->send_lowat = clcf->send_lowat;
p->length = -1;
if (u->input_filter_init
&& u->input_filter_init(p->input_ctx) != NGX_OK) //上游服务器返回包体filter初始化
{
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
return;
}
u->read_event_handler = ngx_http_upstream_process_upstream; //上游包体数据接收处理
r->write_event_handler = ngx_http_upstream_process_downstream; //下游包体数据传送处理
ngx_http_upstream_process_upstream(r, u); //上游包体处理
}