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

📄 mod_proxy_http.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 5 页
字号:
        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:        /* shouldn't be possible */        status = APR_EINVAL;        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->hostname ? p_conn->hostname: "",                     c->remote_ip,                     c->remote_host ? c->remote_host: "");        return status;    }    return APR_SUCCESS;}static void process_proxy_header(request_rec* r, proxy_dir_conf* c,                      const char* key, const char* value){    static const char* date_hdrs[]        = { "Date", "Expires", "Last-Modified", NULL } ;    static const struct {        const char* name;        ap_proxy_header_reverse_map_fn func;    } transform_hdrs[] = {        { "Location", ap_proxy_location_reverse_map } ,        { "Content-Location", ap_proxy_location_reverse_map } ,        { "URI", ap_proxy_location_reverse_map } ,        { "Destination", ap_proxy_location_reverse_map } ,        { "Set-Cookie", ap_proxy_cookie_reverse_map } ,        { NULL, NULL }    } ;    int i ;    for ( i = 0 ; date_hdrs[i] ; ++i ) {        if ( !strcasecmp(date_hdrs[i], key) ) {            apr_table_add(r->headers_out, key,                ap_proxy_date_canon(r->pool, value)) ;            return ;        }    }    for ( i = 0 ; transform_hdrs[i].name ; ++i ) {        if ( !strcasecmp(transform_hdrs[i].name, key) ) {            apr_table_add(r->headers_out, key,                (*transform_hdrs[i].func)(r, c, value)) ;            return ;       }    }    apr_table_add(r->headers_out, key, value) ;    return ;}/* * Note: pread_len is the length of the response that we've  mistakenly * read (assuming that we don't consider that an  error via * ProxyBadHeader StartBody). This depends on buffer actually being * local storage to the calling code in order for pread_len to make * any sense at all, since we depend on buffer still containing * what was read by ap_getline() upon return. */static void ap_proxy_read_headers(request_rec *r, request_rec *rr,                                  char *buffer, int size,                                  conn_rec *c, int *pread_len){    int len;    char *value, *end;    char field[MAX_STRING_LEN];    int saw_headers = 0;    void *sconf = r->server->module_config;    proxy_server_conf *psc;    proxy_dir_conf *dconf;    dconf = ap_get_module_config(r->per_dir_config, &proxy_module);    psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);    r->headers_out = apr_table_make(r->pool, 20);    *pread_len = 0;    /*     * Read header lines until we get the empty separator line, a read error,     * the connection closes (EOF), or we timeout.     */    while ((len = ap_getline(buffer, size, rr, 1)) > 0) {        if (!(value = strchr(buffer, ':'))) {     /* Find the colon separator */            /* We may encounter invalid headers, usually from buggy             * MS IIS servers, so we need to determine just how to handle             * them. We can either ignore them, assume that they mark the             * start-of-body (eg: a missing CRLF) or (the default) mark             * the headers as totally bogus and return a 500. The sole             * exception is an extra "HTTP/1.0 200, OK" line sprinkled             * in between the usual MIME headers, which is a favorite             * IIS bug.             */             /* XXX: The mask check is buggy if we ever see an HTTP/1.10 */            if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) {                if (psc->badopt == bad_error) {                    /* Nope, it wasn't even an extra HTTP header. Give up. */                    r->headers_out = NULL;                    return ;                }                else if (psc->badopt == bad_body) {                    /* if we've already started loading headers_out, then                     * return what we've accumulated so far, in the hopes                     * that they are useful; also note that we likely pre-read                     * the first line of the response.                     */                    if (saw_headers) {                        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,                         "proxy: Starting body due to bogus non-header in headers "                         "returned by %s (%s)", r->uri, r->method);                        *pread_len = len;                        return ;                    } else {                         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,                         "proxy: No HTTP headers "                         "returned by %s (%s)", r->uri, r->method);                        return ;                    }                }            }            /* this is the psc->badopt == bad_ignore case */            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,                         "proxy: Ignoring bogus HTTP header "                         "returned by %s (%s)", r->uri, r->method);            continue;        }        *value = '\0';        ++value;        /* XXX: RFC2068 defines only SP and HT as whitespace, this test is         * wrong... and so are many others probably.         */        while (apr_isspace(*value))            ++value;            /* Skip to start of value   */        /* should strip trailing whitespace as well */        for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)            *end = '\0';        /* make sure we add so as not to destroy duplicated headers         * Modify headers requiring canonicalisation and/or affected         * by ProxyPassReverse and family with process_proxy_header         */        process_proxy_header(r, dconf, buffer, value) ;        saw_headers = 1;        /* the header was too long; at the least we should skip extra data */        if (len >= size - 1) {            while ((len = ap_getline(field, MAX_STRING_LEN, rr, 1))                    >= MAX_STRING_LEN - 1) {                /* soak up the extra data */            }            if (len == 0) /* time to exit the larger loop as well */                break;        }    }}static int addit_dammit(void *v, const char *key, const char *val){    apr_table_addn(v, key, val);    return 1;}staticapr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,                                            proxy_conn_rec *backend,                                            conn_rec *origin,                                            proxy_server_conf *conf,                                            char *server_portstr) {    conn_rec *c = r->connection;    char buffer[HUGE_STRING_LEN];    const char *buf;    char keepchar;    request_rec *rp;    apr_bucket *e;    apr_bucket_brigade *bb;    int len, backasswards;    int interim_response; /* non-zero whilst interim 1xx responses                           * are being read. */    int pread_len = 0;    apr_table_t *save_table;    int backend_broke = 0;    bb = apr_brigade_create(p, c->bucket_alloc);    /* 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;    do {        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) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "proxy: error reading status line from remote "                          "server %s", backend->hostname);            return ap_proxyerror(r, HTTP_BAD_GATEWAY,                                 "Error reading from remote server");        }        /* XXX: Is this a real headers length send from remote? */        backend->worker->s->read += len;        /* 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)) {                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. */            /* First, tuck away all already existing cookies */            save_table = apr_table_make(r->pool, 2);            apr_table_do(addit_dammit, save_table, r->headers_out,                         "Set-Cookie", NULL);            /* shove the headers direct into r->headers_out */            ap_proxy_read_headers(r, rp, buffer, sizeof(buffer), origin,                                  &pread_len);            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);                backend->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;            }            /* Now, add in the just read cookies */            apr_table_do(addit_dammit, save_table, r->headers_out,                         "Set-Cookie", NULL);            /* and now load 'em all in */            if (!apr_is_empty_table(save_table)) {                apr_table_unset(r->headers_out, "Set-Cookie");                r->headers_out = apr_table_overlay(r->pool,                                                   r->headers_out,                                                   save_table);            }            /* 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";                 *                 * To help mitigate HTTP Splitting, unset Content-Length                 * and shut down the backend server connection                 * XXX: We aught to treat such a response as uncachable                 */                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", backend->hostname);                backend->close += 1;            }            /* strip connection listed hop-by-hop headers from response */            backend->close += ap_proxy_liststr(apr_table_get(r->headers_out,                                                             "Connection"),                                              "close");            ap_proxy_clear_connection(p, r->headers_out);

⌨️ 快捷键说明

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