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

📄 mod_proxy_http.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 5 页
字号:
        cl_val = atol(old_cl_val);    }    terminate_headers(bucket_alloc, header_brigade);    while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))    {        apr_brigade_length(input_brigade, 1, &bytes);        bytes_streamed += bytes;        /* If this brigade contains EOS, either stop or remove it. */        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {            seen_eos = 1;            /* We can't pass this EOS to the output_filters. */            e = APR_BRIGADE_LAST(input_brigade);            apr_bucket_delete(e);        }        /* C-L < bytes streamed?!?         * We will error out after the body is completely         * consumed, but we can't stream more bytes at the         * back end since they would in part be interpreted         * as another request!  If nothing is sent, then         * just send nothing.         *         * Prevents HTTP Response Splitting.         */        if (bytes_streamed > cl_val)             continue;        if (header_brigade) {            /* we never sent the header brigade, so go ahead and             * take care of that now             */            bb = header_brigade;            /*             * Save input_brigade in bb brigade. (At least) in the SSL case             * input_brigade contains transient buckets whose data would get             * overwritten during the next call of ap_get_brigade in the loop.             * ap_save_brigade ensures these buckets to be set aside.             * Calling ap_save_brigade with NULL as filter is OK, because             * bb brigade already has been created and does not need to get             * created by ap_save_brigade.             */            status = ap_save_brigade(NULL, &bb, &input_brigade, p);            if (status != APR_SUCCESS) {                return status;            }            header_brigade = NULL;        }        else {            bb = input_brigade;        }        /* Once we hit EOS, we are ready to flush. */        status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, seen_eos);        if (status != APR_SUCCESS) {            return status;        }        if (seen_eos) {            break;        }        status = ap_get_brigade(r->input_filters, input_brigade,                                AP_MODE_READBYTES, APR_BLOCK_READ,                                HUGE_STRING_LEN);        if (status != APR_SUCCESS) {            return status;        }    }    if (bytes_streamed != cl_val) {        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                     "proxy: client %s given Content-Length did not match"                     " number of body bytes read", r->connection->remote_ip);        return APR_EOF;    }    if (header_brigade) {        /* we never sent the header brigade since there was no request         * body; send it now with the flush flag         */        bb = header_brigade;        status = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);    }    return status;}static apr_status_t spool_reqbody_cl(apr_pool_t *p,                                     request_rec *r,                                     proxy_conn_rec *p_conn,                                     conn_rec *origin,                                     apr_bucket_brigade *header_brigade,                                     apr_bucket_brigade *input_brigade,                                     int force_cl){    int seen_eos = 0;    apr_status_t status;    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;    apr_bucket_brigade *body_brigade;    apr_bucket *e;    apr_off_t bytes, bytes_spooled = 0, fsize = 0;    apr_file_t *tmpfile = NULL;    body_brigade = apr_brigade_create(p, bucket_alloc);    while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))    {        /* If this brigade contains EOS, either stop or remove it. */        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {            seen_eos = 1;            /* We can't pass this EOS to the output_filters. */            e = APR_BRIGADE_LAST(input_brigade);            apr_bucket_delete(e);        }        apr_brigade_length(input_brigade, 1, &bytes);        if (bytes_spooled + bytes > MAX_MEM_SPOOL) {            /* can't spool any more in memory; write latest brigade to disk */            if (tmpfile == NULL) {                const char *temp_dir;                char *template;                status = apr_temp_dir_get(&temp_dir, p);                if (status != APR_SUCCESS) {                    ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,                                 "proxy: search for temporary directory failed");                    return status;                }                apr_filepath_merge(&template, temp_dir,                                   "modproxy.tmp.XXXXXX",                                   APR_FILEPATH_NATIVE, p);                status = apr_file_mktemp(&tmpfile, template, 0, p);                if (status != APR_SUCCESS) {                    ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,                                 "proxy: creation of temporary file in directory %s failed",                                 temp_dir);                    return status;                }            }            for (e = APR_BRIGADE_FIRST(input_brigade);                 e != APR_BRIGADE_SENTINEL(input_brigade);                 e = APR_BUCKET_NEXT(e)) {                const char *data;                apr_size_t bytes_read, bytes_written;                apr_bucket_read(e, &data, &bytes_read, APR_BLOCK_READ);                status = apr_file_write_full(tmpfile, data, bytes_read, &bytes_written);                if (status != APR_SUCCESS) {                    const char *tmpfile_name;                    if (apr_file_name_get(&tmpfile_name, tmpfile) != APR_SUCCESS) {                        tmpfile_name = "(unknown)";                    }                    ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,                                 "proxy: write to temporary file %s failed",                                 tmpfile_name);                    return status;                }                AP_DEBUG_ASSERT(bytes_read == bytes_written);                fsize += bytes_written;            }            apr_brigade_cleanup(input_brigade);        }        else {            /*             * Save input_brigade in body_brigade. (At least) in the SSL case             * input_brigade contains transient buckets whose data would get             * overwritten during the next call of ap_get_brigade in the loop.             * ap_save_brigade ensures these buckets to be set aside.             * Calling ap_save_brigade with NULL as filter is OK, because             * body_brigade already has been created and does not need to get             * created by ap_save_brigade.             */            status = ap_save_brigade(NULL, &body_brigade, &input_brigade, p);            if (status != APR_SUCCESS) {                return status;            }        }        bytes_spooled += bytes;        if (seen_eos) {            break;        }        status = ap_get_brigade(r->input_filters, input_brigade,                                AP_MODE_READBYTES, APR_BLOCK_READ,                                HUGE_STRING_LEN);        if (status != APR_SUCCESS) {            return status;        }    }    if (bytes_spooled || force_cl) {        add_cl(p, bucket_alloc, header_brigade, apr_off_t_toa(p, bytes_spooled));    }    terminate_headers(bucket_alloc, header_brigade);    APR_BRIGADE_CONCAT(header_brigade, body_brigade);    if (tmpfile) {        /* For platforms where the size of the file may be larger than         * that which can be stored in a single bucket (where the         * length field is an apr_size_t), split it into several         * buckets: */        if (sizeof(apr_off_t) > sizeof(apr_size_t)            && fsize > AP_MAX_SENDFILE) {            e = apr_bucket_file_create(tmpfile, 0, AP_MAX_SENDFILE, p,                                       bucket_alloc);            while (fsize > AP_MAX_SENDFILE) {                apr_bucket *ce;                apr_bucket_copy(e, &ce);                APR_BRIGADE_INSERT_TAIL(header_brigade, ce);                e->start += AP_MAX_SENDFILE;                fsize -= AP_MAX_SENDFILE;            }            e->length = (apr_size_t)fsize; /* Resize just the last bucket */        }        else {            e = apr_bucket_file_create(tmpfile, 0, (apr_size_t)fsize, p,                                       bucket_alloc);        }        APR_BRIGADE_INSERT_TAIL(header_brigade, e);    }    /* This is all a single brigade, pass with flush flagged */    status = pass_brigade(bucket_alloc, r, p_conn, origin, header_brigade, 1);    return status;}staticapr_status_t ap_proxy_http_request(apr_pool_t *p, request_rec *r,                                   proxy_conn_rec *p_conn, conn_rec *origin,                                   proxy_server_conf *conf,                                   apr_uri_t *uri,                                   char *url, char *server_portstr){    conn_rec *c = r->connection;    apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;    apr_bucket_brigade *header_brigade;    apr_bucket_brigade *input_brigade;    apr_bucket_brigade *temp_brigade;    apr_bucket *e;    char *buf;    const apr_array_header_t *headers_in_array;    const apr_table_entry_t *headers_in;    int counter;    apr_status_t status;    enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED, RB_SPOOL_CL};    enum rb_methods rb_method = RB_INIT;    const char *old_cl_val = NULL;    const char *old_te_val = NULL;    apr_off_t bytes_read = 0;    apr_off_t bytes;    int force10;    apr_table_t *headers_in_copy;    header_brigade = apr_brigade_create(p, origin->bucket_alloc);    /*     * Send the HTTP/1.1 request to the remote server     */    if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {        buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.0" CRLF, NULL);        force10 = 1;        p_conn->close++;    } else {        buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);        force10 = 0;    }    if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) {        origin->keepalive = AP_CONN_CLOSE;        p_conn->close++;    }    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);    if (conf->preserve_host == 0) {        if (uri->port_str && uri->port != DEFAULT_HTTP_PORT) {            buf = apr_pstrcat(p, "Host: ", uri->hostname, ":", uri->port_str,                              CRLF, NULL);        } else {            buf = apr_pstrcat(p, "Host: ", uri->hostname, CRLF, NULL);        }    }    else {        /* don't want to use r->hostname, as the incoming header might have a         * port attached         */        const char* hostname = apr_table_get(r->headers_in,"Host");        if (!hostname) {            hostname =  r->server->server_hostname;            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,                          "proxy: no HTTP 0.9 request (with no host line) "                          "on incoming request and preserve host set "                          "forcing hostname to be %s for uri %s",                          hostname,                          r->uri );        }        buf = apr_pstrcat(p, "Host: ", hostname, CRLF, NULL);    }    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);    /* handle Via */    if (conf->viaopt == via_block) {        /* Block all outgoing Via: headers */        apr_table_unset(r->headers_in, "Via");    } else if (conf->viaopt != via_off) {        const char *server_name = ap_get_server_name(r);        /* If USE_CANONICAL_NAME_OFF was configured for the proxy virtual host,         * then the server name returned by ap_get_server_name() is the         * origin server name (which does make too much sense with Via: headers)         * so we use the proxy vhost's name instead.         */        if (server_name == r->hostname)            server_name = r->server->server_hostname;        /* Create a "Via:" request header entry and merge it */        /* Generate outgoing Via: header with/without server comment: */        apr_table_mergen(r->headers_in, "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),                                        server_name, server_portstr,                                        AP_SERVER_BASEVERSION)

⌨️ 快捷键说明

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