⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ngx_http_upstream.c

📁 Nginx是一个高性能的HTTP和反向代理服务器
💻 C
📖 第 1 页 / 共 5 页
字号:
        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 + -