ngx_http_request.c

来自「Nginx是一个高性能的HTTP和反向代理服务器」· C语言 代码 · 共 2,528 行 · 第 1/5 页

C
2,528
字号
                    ngx_http_close_request(r, 0);                    return;                }            }            for (i = 0; i < hc->nbusy - 1; i++) {                f = hc->busy[i];                hc->free[hc->nfree++] = f;                f->pos = f->start;                f->last = f->start;            }            hc->busy[0] = b;            hc->nbusy = 1;        }    }    ngx_http_request_done(r, 0);    c->data = hc;    ngx_add_timer(rev, clcf->keepalive_timeout);    if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {        ngx_http_close_connection(c);        return;    }    wev = c->write;    wev->handler = ngx_http_empty_handler;    if (b->pos < b->last) {        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");#if (NGX_STAT_STUB)        ngx_atomic_fetch_add(ngx_stat_reading, 1);#endif        hc->pipeline = 1;        c->log->action = "reading client pipelined request line";        ngx_http_init_request(rev);        return;    }    hc->pipeline = 0;    /*     * To keep a memory footprint as small as possible for an idle     * keepalive connection we try to free the ngx_http_request_t and     * c->buffer's memory if they were allocated outside the c->pool.     * The large header buffers are always allocated outside the c->pool and     * are freed too.     */    if (ngx_pfree(c->pool, r) == NGX_OK) {        hc->request = NULL;    }    b = c->buffer;    if (ngx_pfree(c->pool, b->start) == NGX_OK) {        /*         * the special note for ngx_http_keepalive_handler() that         * c->buffer's memory was freed         */        b->pos = NULL;    } else {        b->pos = b->start;        b->last = b->start;    }    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",                   hc->free, hc->nfree);    if (hc->free) {        for (i = 0; i < hc->nfree; i++) {            ngx_pfree(c->pool, hc->free[i]->start);            hc->free[i] = NULL;        }        hc->nfree = 0;    }    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",                   hc->busy, hc->nbusy);    if (hc->busy) {        for (i = 0; i < hc->nbusy; i++) {            ngx_pfree(c->pool, hc->busy[i]->start);            hc->busy[i] = NULL;        }        hc->nbusy = 0;    }#if (NGX_HTTP_SSL)    if (c->ssl) {        ngx_ssl_free_buffer(c);    }#endif    rev->handler = ngx_http_keepalive_handler;    if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {        if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {            ngx_http_close_connection(c);            return;        }    }    c->log->action = "keepalive";    if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {        if (ngx_tcp_push(c->fd) == -1) {            ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");            ngx_http_close_connection(c);            return;        }        c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;        tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;    } else {        tcp_nodelay = 1;    }    if (tcp_nodelay        && clcf->tcp_nodelay        && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)    {        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");        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_close_connection(c);            return;        }        c->tcp_nodelay = NGX_TCP_NODELAY_SET;    }#if 0    /* if ngx_http_request_t was freed then we need some other place */    r->http_state = NGX_HTTP_KEEPALIVE_STATE;#endif    c->idle = 1;    if (rev->ready) {        ngx_http_keepalive_handler(rev);    }}static voidngx_http_keepalive_handler(ngx_event_t *rev){    size_t             size;    ssize_t            n;    ngx_buf_t         *b;    ngx_connection_t  *c;    c = rev->data;    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");    if (rev->timedout || c->close) {        ngx_http_close_connection(c);        return;    }#if (NGX_HAVE_KQUEUE)    if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {        if (rev->pending_eof) {            c->log->handler = NULL;            ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,                          "kevent() reported that client %V closed "                          "keepalive connection", &c->addr_text);#if (NGX_HTTP_SSL)            if (c->ssl) {                c->ssl->no_send_shutdown = 1;            }#endif            ngx_http_close_connection(c);            return;        }    }#endif    b = c->buffer;    size = b->end - b->start;    if (b->pos == NULL) {        /*         * The c->buffer's memory was freed by ngx_http_set_keepalive().         * However, the c->buffer->start and c->buffer->end were not changed         * to keep the buffer size.         */        b->pos = ngx_palloc(c->pool, size);        if (b->pos == NULL) {            ngx_http_close_connection(c);            return;        }        b->start = b->pos;        b->last = b->pos;        b->end = b->pos + size;    }    /*     * MSIE closes a keepalive connection with RST flag     * so we ignore ECONNRESET here.     */    c->log_error = NGX_ERROR_IGNORE_ECONNRESET;    ngx_set_socket_errno(0);    n = c->recv(c, b->last, size);    c->log_error = NGX_ERROR_INFO;    if (n == NGX_AGAIN) {        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {            ngx_http_close_connection(c);        }        return;    }    if (n == NGX_ERROR) {        ngx_http_close_connection(c);        return;    }    c->log->handler = NULL;    if (n == 0) {        ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,                      "client %V closed keepalive connection", &c->addr_text);        ngx_http_close_connection(c);        return;    }    b->last += n;#if (NGX_STAT_STUB)    ngx_atomic_fetch_add(ngx_stat_reading, 1);#endif    c->log->handler = ngx_http_log_error;    c->log->action = "reading client request line";    c->idle = 0;    ngx_http_init_request(rev);}static voidngx_http_set_lingering_close(ngx_http_request_t *r){    ngx_event_t               *rev, *wev;    ngx_connection_t          *c;    ngx_http_core_loc_conf_t  *clcf;    c = r->connection;    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);    rev = c->read;    rev->handler = ngx_http_lingering_close_handler;    r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);    ngx_add_timer(rev, clcf->lingering_timeout);    if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {        ngx_http_close_request(r, 0);        return;    }    wev = c->write;    wev->handler = ngx_http_empty_handler;    if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {        if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {            ngx_http_close_request(r, 0);            return;        }    }    if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {        ngx_connection_error(c, ngx_socket_errno,                             ngx_shutdown_socket_n " failed");        ngx_http_close_request(r, 0);        return;    }    if (rev->ready) {        ngx_http_lingering_close_handler(rev);    }}static voidngx_http_lingering_close_handler(ngx_event_t *rev){    ssize_t                    n;    ngx_msec_t                 timer;    ngx_connection_t          *c;    ngx_http_request_t        *r;    ngx_http_core_loc_conf_t  *clcf;    u_char                     buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];    c = rev->data;    r = c->data;    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,                   "http lingering close handler");    if (rev->timedout) {        c->timedout = 1;        ngx_http_close_request(r, 0);        return;    }    timer = (ngx_msec_t) (r->lingering_time - ngx_time());    if (timer <= 0) {        ngx_http_close_request(r, 0);        return;    }    do {        n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);        if (n == NGX_ERROR || n == 0) {            ngx_http_close_request(r, 0);            return;        }    } while (rev->ready);    if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {        ngx_http_close_request(r, 0);        return;    }    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);    timer *= 1000;    if (timer > clcf->lingering_timeout) {        timer = clcf->lingering_timeout;    }    ngx_add_timer(rev, timer);}voidngx_http_empty_handler(ngx_event_t *wev){    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");    return;}voidngx_http_request_empty_handler(ngx_http_request_t *r){    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                   "http request empty handler");    return;}ngx_int_tngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags){    ngx_buf_t    *b;    ngx_chain_t   out;    b = ngx_calloc_buf(r->pool);    if (b == NULL) {        return NGX_ERROR;    }    if (flags & NGX_HTTP_LAST) {        b->last_buf = 1;    }    if (flags & NGX_HTTP_FLUSH) {        b->flush = 1;    }    out.buf = b;    out.next = NULL;    return ngx_http_output_filter(r, &out);}static ngx_int_tngx_http_post_action(ngx_http_request_t *r){    ngx_http_core_loc_conf_t  *clcf;    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);    if (clcf->post_action.data == NULL) {        return NGX_DECLINED;    }    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,                   "post action: \"%V\"", &clcf->post_action);    r->http_version = NGX_HTTP_VERSION_9;    r->header_only = 1;    r->post_action = 1;    r->read_event_handler = ngx_http_block_reading;    if (clcf->post_action.data[0] == '/') {        ngx_http_internal_redirect(r, &clcf->post_action, NULL);    } else {        ngx_http_named_location(r, &clcf->post_action);    }    return NGX_OK;}static voidngx_http_close_request(ngx_http_request_t *r, ngx_int_t error){    ngx_connection_t  *c;    c = r->connection;    ngx_http_request_done(r->main, error);    ngx_http_close_connection(c);}static voidngx_http_request_done(ngx_http_request_t *r, ngx_int_t error){    ngx_log_t                  *log;    ngx_uint_t                  i, n;    struct linger               linger;    ngx_http_cleanup_t         *cln;    ngx_http_log_ctx_t         *ctx;    ngx_http_handler_pt        *log_handler;    ngx_http_core_loc_conf_t   *clcf;    ngx_http_core_main_conf_t  *cmcf;    log = r->connection->log;    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");    if (r->pool == NULL) {        ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");        return;    }    for (cln = r->cleanup; cln; cln = cln->next) {        if (cln->handler) {            cln->handler(cln->data);        }    }#if (NGX_STAT_STUB)    if (r->stat_reading) {        ngx_atomic_fetch_add(ngx_stat_reading, -1);    }    if (r->stat_writing) {        ngx_atomic_fetch_add(ngx_stat_writing, -1);    }#endif    if (error && r->headers_out.status == 0) {        r->headers_out.status = error;    }    c

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?