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

📄 proxy_http.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Yes I hate gotos.  This is the subrequest shortcut */skip_body:    /* Handle Connection: header */    if (!force10 && p_conn->close) {        buf = apr_pstrdup(p, "Connection: close" CRLF);        ap_xlate_proto_to_ascii(buf, strlen(buf));        e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(header_brigade, e);    }       /* send the request body, if any. */    switch(rb_method) {    case RB_STREAM_CHUNKED:        status = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,                                         input_brigade);        break;    case RB_STREAM_CL:        status = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,                                    input_brigade, old_cl_val);        break;    case RB_SPOOL_CL:        status = spool_reqbody_cl(p, r, p_conn, origin, header_brigade,                                  input_brigade, (old_cl_val != NULL)                                              || (old_te_val != NULL)                                              || (bytes_read > 0));        break;    default:        ap_assert(1 != 1);        break;    }    if (status != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,                     "proxy: pass request body failed to %pI (%s)"                     " from %s (%s)",                     p_conn->addr, p_conn->name ? p_conn->name: "",                     c->remote_ip, c->remote_host ? c->remote_host: "");        return status;    }    return APR_SUCCESS;}staticapr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,                                            proxy_http_conn_t *p_conn,                                            conn_rec *origin,                                            proxy_conn_rec *backend,                                            proxy_server_conf *conf,                                            apr_bucket_brigade *bb,                                            char *server_portstr) {    conn_rec *c = r->connection;    char buffer[HUGE_STRING_LEN];    const char *buf;    char keepchar;    request_rec *rp;    apr_bucket *e;    int len, backasswards;    int received_continue = 1; /* flag to indicate if we should                                * loop over response parsing logic                                * in the case that the origin told us                                * to HTTP_CONTINUE                                */    /* Get response from the remote server, and pass it up the     * filter chain     */    rp = ap_proxy_make_fake_req(origin, r);    /* In case anyone needs to know, this is a fake request that is really a     * response.     */    rp->proxyreq = PROXYREQ_RESPONSE;    while (received_continue) {        apr_brigade_cleanup(bb);        len = ap_getline(buffer, sizeof(buffer), rp, 0);        if (len == 0) {            /* handle one potential stray CRLF */            len = ap_getline(buffer, sizeof(buffer), rp, 0);        }        if (len <= 0) {            apr_socket_close(p_conn->sock);            backend->connection = NULL;            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "proxy: error reading status line from remote "                          "server %s", p_conn->name);            return ap_proxyerror(r, HTTP_BAD_GATEWAY,                                 "Error reading from remote server");        }        /* Is it an HTTP/1 response?         * This is buggy if we ever see an HTTP/1.10         */        if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {            int major, minor;            if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {                major = 1;                minor = 1;            }            /* If not an HTTP/1 message or             * if the status line was > 8192 bytes             */            else if ((buffer[5] != '1') || (len >= sizeof(buffer)-1)) {                apr_socket_close(p_conn->sock);                backend->connection = NULL;                return ap_proxyerror(r, HTTP_BAD_GATEWAY,                apr_pstrcat(p, "Corrupt status line returned by remote "                            "server: ", buffer, NULL));            }            backasswards = 0;            keepchar = buffer[12];            buffer[12] = '\0';            r->status = atoi(&buffer[9]);            if (keepchar != '\0') {                buffer[12] = keepchar;            } else {                /* 2616 requires the space in Status-Line; the origin                 * server may have sent one but ap_rgetline_core will                 * have stripped it. */                buffer[12] = ' ';                buffer[13] = '\0';            }            r->status_line = apr_pstrdup(p, &buffer[9]);                        /* read the headers. */            /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers*/            /* Also, take care with headers with multiple occurences. */            r->headers_out = ap_proxy_read_headers(r, rp, buffer,                                                   sizeof(buffer), origin);            if (r->headers_out == NULL) {                ap_log_error(APLOG_MARK, APLOG_WARNING, 0,                             r->server, "proxy: bad HTTP/%d.%d header "                             "returned by %s (%s)", major, minor, r->uri,                             r->method);                p_conn->close += 1;                /*                 * ap_send_error relies on a headers_out to be present. we                 * are in a bad position here.. so force everything we send out                 * to have nothing to do with the incoming packet                 */                r->headers_out = apr_table_make(r->pool,1);                r->status = HTTP_BAD_GATEWAY;                r->status_line = "bad gateway";                return r->status;            }            /* can't have both Content-Length and Transfer-Encoding */            if (apr_table_get(r->headers_out, "Transfer-Encoding")                && apr_table_get(r->headers_out, "Content-Length")) {                /* 2616 section 4.4, point 3: "if both Transfer-Encoding                 * and Content-Length are received, the latter MUST be                 * ignored"; so unset it here to prevent any confusion                 * later. */                apr_table_unset(r->headers_out, "Content-Length");                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,                             r->server,                             "proxy: server %s returned Transfer-Encoding and Content-Length",                             p_conn->name);                p_conn->close += 1;            }                        /* strip connection listed hop-by-hop headers from response */            p_conn->close += ap_proxy_liststr(apr_table_get(r->headers_out,                                                            "Connection"),                                              "close");            ap_proxy_clear_connection(p, r->headers_out);            if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {                ap_set_content_type(r, apr_pstrdup(p, buf));            }                        ap_proxy_pre_http_request(origin,rp);            /* handle Via header in response */            if (conf->viaopt != via_off && conf->viaopt != via_block) {                /* create a "Via:" response header entry and merge it */                apr_table_mergen(r->headers_out, "Via",                                 (conf->viaopt == via_full)                                     ? apr_psprintf(p, "%d.%d %s%s (%s)",                                           HTTP_VERSION_MAJOR(r->proto_num),                                           HTTP_VERSION_MINOR(r->proto_num),                                           ap_get_server_name(r),                                           server_portstr,                                           AP_SERVER_BASEVERSION)                                     : apr_psprintf(p, "%d.%d %s%s",                                           HTTP_VERSION_MAJOR(r->proto_num),                                           HTTP_VERSION_MINOR(r->proto_num),                                           ap_get_server_name(r),                                           server_portstr)                );            }            /* cancel keepalive if HTTP/1.0 or less */            if ((major < 1) || (minor < 1)) {                p_conn->close += 1;                origin->keepalive = AP_CONN_CLOSE;            }        } else {            /* an http/0.9 response */            backasswards = 1;            r->status = 200;            r->status_line = "200 OK";            p_conn->close += 1;        }        if ( r->status != HTTP_CONTINUE ) {            received_continue = 0;        } else {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,                         "proxy: HTTP: received 100 CONTINUE");        }        /* we must accept 3 kinds of date, but generate only 1 kind of date */        if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {            apr_table_set(r->headers_out, "Date",                          ap_proxy_date_canon(p, buf));        }        if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {            apr_table_set(r->headers_out, "Expires",                          ap_proxy_date_canon(p, buf));        }        if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {            apr_table_set(r->headers_out, "Last-Modified",                          ap_proxy_date_canon(p, buf));        }        /* munge the Location and URI response headers according to         * ProxyPassReverse         */        if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {            apr_table_set(r->headers_out, "Location",                          ap_proxy_location_reverse_map(r, conf, buf));        }        if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {            apr_table_set(r->headers_out, "Content-Location",                          ap_proxy_location_reverse_map(r, conf, buf));        }        if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {            apr_table_set(r->headers_out, "URI",                          ap_proxy_location_reverse_map(r, conf, buf));        }        if ((r->status == 401) && (conf->error_override != 0)) {            const char *wa = "WWW-Authenticate";            if ((buf = apr_table_get(r->headers_out, wa))) {                apr_table_set(r->err_headers_out, wa, buf);            } else {                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                             "proxy: origin server sent 401 without WWW-Authenticate header");            }        }        r->sent_bodyct = 1;        /* Is it an HTTP/0.9 response? If so, send the extra data */        if (backasswards) {            apr_ssize_t cntr = len;            e = apr_bucket_heap_create(buffer, cntr, NULL, c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(bb, e);        }        /* send body - but only if a body is expected */        if ((!r->header_only) &&                   /* not HEAD request */            (r->status > 199) &&                   /* not any 1xx response */            (r->status != HTTP_NO_CONTENT) &&      /* not 204 */            (r->status != HTTP_RESET_CONTENT) &&   /* not 205 */            (r->status != HTTP_NOT_MODIFIED)) {    /* not 304 */            /* We need to copy the output headers and treat them as input             * headers as well.  BUT, we need to do this before we remove             * TE, so that they are preserved accordingly for             * ap_http_filter to know where to end.             */            rp->headers_in = apr_table_copy(r->pool, r->headers_out);            apr_table_unset(r->headers_out,"Transfer-Encoding");            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: start body send");                         /*             * if we are overriding the errors, we can't put the content             * of the page into the brigade             */            if ( (conf->error_override ==0) || r->status < 400 ) {                /* read the body, pass it to the output filters */                int finish = FALSE;                while (ap_get_brigade(rp->input_filters,                                       bb,                                       AP_MODE_READBYTES,                                       APR_BLOCK_READ,                                       conf->io_buffer_size) == APR_SUCCESS) {#if DEBUGGING                    {                    apr_off_t readbytes;                    apr_brigade_length(bb, 0, &readbytes);                    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,                                 r->server, "proxy (PID %d): readbytes: %#x",                                 getpid(), readbytes);                    }#endif                    /* sanity check */                    if (APR_BRIGADE_EMPTY(bb)) {                        apr_brigade_cleanup(bb);                        break;                    }                    /* found the last brigade? */                    if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {                        /* if this is the last brigade, cleanup the                         * backend connection first to prevent the                         * backend server from hanging around waiting                         * for a slow client to eat these bytes                         */                        ap_proxy_http_cleanup(r, p_conn, backend);                        /* signal that we must leave */                        finish = TRUE;                    }                    /* try send what we read */                    if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS                        || c->aborted) {                        /* Ack! Phbtt! Die! User aborted! */                        p_conn->close = 1;  /* this causes socket close below */                        finish = TRUE;                    }                    /* make sure we always clean up after ourselves */                    apr_brigade_cleanup(bb);                    /* if we are done, leave */                    if (TRUE == finish) {                        break;                    }                }            }            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: end body send");        } else {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: header only");        }    }    if ( conf->error_override

⌨️ 快捷键说明

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