📄 ngx_http_upstream.c
字号:
ngx_http_upstream_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } if (u->buffer.last - u->buffer.pos >= (ssize_t) u->length) { if (u->input_filter(u->input_filter_ctx, 0) == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; } ngx_http_upstream_finalize_request(r, u, 0); return; } rev->handler = ngx_http_upstream_process_body_in_memory; ngx_http_upstream_process_body_in_memory(rev);}static ngx_int_tngx_http_upstream_test_connect(ngx_connection_t *c){ int err; socklen_t len;#if (NGX_HAVE_KQUEUE) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { if (c->write->pending_eof) { c->log->action = "connecting to upstream"; (void) ngx_connection_error(c, c->write->kq_errno, "kevent() reported that connect() failed"); return NGX_ERROR; } } else#endif { err = 0; len = sizeof(int); /* * BSDs and Linux return 0 and set a pending error in err * Solaris returns -1 and sets errno */ if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) == -1) { err = ngx_errno; } if (err) { c->log->action = "connecting to upstream"; (void) ngx_connection_error(c, err, "connect() failed"); return NGX_ERROR; } } return NGX_OK;}static voidngx_http_upstream_process_body_in_memory(ngx_event_t *rev){ size_t size; ssize_t n; ngx_buf_t *b; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_upstream_t *u; c = rev->data; r = c->data; u = r->upstream; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream process body on memory"); if (rev->timedout) { ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); ngx_http_upstream_finalize_request(r, u, NGX_ETIMEDOUT); return; } b = &u->buffer; for ( ;; ) { size = b->end - b->last; if (size == 0) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "upstream buffer is too small to read repsonse"); ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; } n = c->recv(c, b->last, size); if (n == NGX_AGAIN) { break; } if (n == 0 || n == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, n); return; } if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; } if (!rev->ready) { break; } } if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; } if (rev->active) { ngx_add_timer(rev, u->conf->read_timeout); } else if (rev->timer_set) { ngx_del_timer(rev); }}static voidngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u){ int tcp_nodelay; ssize_t size; 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); if (rc == NGX_ERROR || rc > NGX_OK || r->post_action || r->header_only) { ngx_http_upstream_finalize_request(r, u, rc); return; } 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; } } } } c = r->connection; 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->peer.connection->read->handler = ngx_http_upstream_process_non_buffered_body; 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, 0); return; } if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { 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, 0); return; } c->tcp_nodelay = NGX_TCP_NODELAY_SET; } size = u->buffer.last - u->buffer.pos; if (size) { u->buffer.last = u->buffer.pos; if (u->input_filter(u->input_filter_ctx, size) == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, 0); return; } ngx_http_upstream_process_non_buffered_body(c->write); } else { u->buffer.pos = u->buffer.start; u->buffer.last = u->buffer.start; if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, 0); return; } if (u->peer.connection->read->ready) { ngx_http_upstream_process_non_buffered_body( u->peer.connection->read); } } return; } /* TODO: preallocate event_pipe bufs, look "Content-Length" */#if 0 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 (u->cacheable) { header = (ngx_http_cache_header_t *) u->buffer->start; 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; 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; }#endif p = u->pipe; p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter; p->output_ctx = r; p->tag = u->output.tag; p->bufs = u->conf->bufs; p->busy_size = u->conf->busy_buffers_size; p->upstream = u->peer.connection; p->downstream = c; p->pool = r->pool; p->log = c->log; p->cacheable = u->cacheable || u->store; p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)); if (p->temp_file == NULL) { ngx_http_upstream_finalize_request(r, u, 0); return; } p->temp_file->file.fd = NGX_INVALID_FILE; p->temp_file->file.log = c->log; p->temp_file->path = u->conf->temp_path; p->temp_file->pool = r->pool; if (u->cacheable || 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 " "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; p->preread_bufs = ngx_alloc_chain_link(r->pool); if (p->preread_bufs == NULL) { ngx_http_upstream_finalize_request(r, u, 0); return; } p->preread_bufs->buf = &u->buffer; p->preread_bufs->next = NULL; u->buffer.recycled = 1; p->preread_size = u->buffer.last - u->buffer.pos; if (u->cacheable) { 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; } if (ngx_event_flags & NGX_USE_AIO_EVENT) { /* the posted aio operation may currupt 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->buffer.last += p->preread_size * as though these bytes were read */ u->buffer.last = u->buffer.pos; 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; u->peer.connection->read->handler = ngx_http_upstream_process_body; r->write_event_handler = ngx_http_upstream_process_downstream; ngx_http_upstream_process_body(u->peer.connection->read);}static voidngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r){ ngx_http_upstream_process_non_buffered_body(r->connection->write);}static voidngx_http_upstream_process_non_buffered_body(ngx_event_t *ev){ size_t size; ssize_t n; ngx_buf_t *b; ngx_int_t rc; ngx_uint_t do_write; ngx_connection_t *c, *downstream, *upstream; ngx_http_request_t *r; ngx_http_upstream_t *u; ngx_http_core_loc_conf_t *clcf; c = ev->data; r = c->data; u = r->upstream; if (ev->write) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream process non buffered downstream"); c->log->action = "sending to client"; } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream process non buffered upstream"); c->log->action = "reading upstream"; } if (ev->timedout) { if (ev->write) { c->timedout = 1; ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); } else { ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); } ngx_http_upstream_finalize_request(r, u, 0); return; } downstream = r->connection; upstream = u->peer.connection; b = &u->buffer; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); do_write = ev->write || u->length == 0; for ( ;; ) { if (do_write) { if (u->out_bufs || u->busy_bufs) { rc = ngx_http_output_filter(r, u->out_bufs); if (downstream->destroyed) { return; } if (rc == NGX_ERROR) { ngx_http_upstream_finalize_request(r, u, 0); return; } ngx_chain_update_chains(&u->free_bufs, &u->busy_bufs, &u->out_bufs, u->output.tag); } if (u->busy_bufs == NULL) { if (u->length == 0 || upstream->read->eof || upstream->read->error) { ngx_http_upstream_finalize_request(r, u, 0); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -