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

📄 mod_proxy_http.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 5 页
字号:
            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) {                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:" 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),                                           server_name,                                           server_portstr,                                           AP_SERVER_BASEVERSION)                                     : apr_psprintf(p, "%d.%d %s%s",                                           HTTP_VERSION_MAJOR(r->proto_num),                                           HTTP_VERSION_MINOR(r->proto_num),                                           server_name,                                           server_portstr)                );            }            /* cancel keepalive if HTTP/1.0 or less */            if ((major < 1) || (minor < 1)) {                backend->close += 1;                origin->keepalive = AP_CONN_CLOSE;            }        } else {            /* an http/0.9 response */            backasswards = 1;            r->status = 200;            r->status_line = "200 OK";            backend->close += 1;        }        interim_response = ap_is_HTTP_INFO(r->status);        if (interim_response) {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,                         "proxy: HTTP: received interim %d response",                         r->status);        }        /* Moved the fixups of Date headers and those affected by         * ProxyPassReverse/etc from here to ap_proxy_read_headers         */        if ((r->status == 401) && (conf->error_override != 0)) {            const char *buf;            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 or did we maybe preread the 1st line of         * the response? If so, load the extra data. These are 2 mutually         * exclusive possibilities, that just happen to require very         * similar behavior.         */        if (backasswards || pread_len) {            apr_ssize_t cntr = (apr_ssize_t)pread_len;            if (backasswards) {                /*@@@FIXME:                 * At this point in response processing of a 0.9 response,                 * we don't know yet whether data is binary or not.                 * mod_charset_lite will get control later on, so it cannot                 * decide on the conversion of this buffer full of data.                 * However, chances are that we are not really talking to an                 * HTTP/0.9 server, but to some different protocol, therefore                 * the best guess IMHO is to always treat the buffer as "text/x":                 */                ap_xlate_proto_to_ascii(buffer, len);                cntr = (apr_ssize_t)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 */            !interim_response &&                   /* not any 1xx response */            (r->status != HTTP_NO_CONTENT) &&      /* not 204 */            (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 || ap_is_HTTP_SUCCESS(r->status)) {                /* read the body, pass it to the output filters */                apr_read_type_e mode = APR_NONBLOCK_READ;                int finish = FALSE;                do {                    apr_off_t readbytes;                    apr_status_t rv;                    rv = ap_get_brigade(rp->input_filters, bb,                                        AP_MODE_READBYTES, mode,                                        conf->io_buffer_size);                    /* ap_get_brigade will return success with an empty brigade                     * for a non-blocking read which would block: */                    if (APR_STATUS_IS_EAGAIN(rv)                        || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb))) {                        /* flush to the client and switch to blocking mode */                        e = apr_bucket_flush_create(c->bucket_alloc);                        APR_BRIGADE_INSERT_TAIL(bb, e);                        if (ap_pass_brigade(r->output_filters, bb)                            || c->aborted) {                            backend->close = 1;                            break;                        }                        apr_brigade_cleanup(bb);                        mode = APR_BLOCK_READ;                        continue;                    }                    else if (rv == APR_EOF) {                        break;                    }                    else if (rv != APR_SUCCESS) {                        /* In this case, we are in real trouble because                         * our backend bailed on us. Pass along a 502 error                         * error bucket                         */                        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c,                                      "proxy: error reading response");                        ap_proxy_backend_broke(r, bb);                        ap_pass_brigade(r->output_filters, bb);                        backend_broke = 1;                        backend->close = 1;                        break;                    }                    /* next time try a non-blocking read */                    mode = APR_NONBLOCK_READ;                    apr_brigade_length(bb, 0, &readbytes);                    backend->worker->s->read += readbytes;#if DEBUGGING                    {                    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))) {                        /* 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! */                        backend->close = 1;  /* this causes socket close below */                        finish = TRUE;                    }                    /* make sure we always clean up after ourselves */                    apr_brigade_cleanup(bb);                } while (!finish);            }            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: end body send");        }        else if (!interim_response) {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: header only");            /* Pass EOS bucket down the filter chain. */            e = apr_bucket_eos_create(c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(bb, e);            if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS                || c->aborted) {                /* Ack! Phbtt! Die! User aborted! */                backend->close = 1;  /* this causes socket close below */            }            apr_brigade_cleanup(bb);        }    } while (interim_response);    /* If our connection with the client is to be aborted, return DONE. */    if (c->aborted || backend_broke) {        return DONE;    }    if (conf->error_override) {        /* the code above this checks for 'OK' which is what the hook expects */        if (ap_is_HTTP_SUCCESS(r->status))            return OK;        else {            /* clear r->status for override error, otherwise ErrorDocument             * thinks that this is a recursive error, and doesn't find the             * custom error page             */            int status = r->status;            r->status = HTTP_OK;            /* Discard body, if one is expected */            if ((status != HTTP_NO_CONTENT) && /* not 204 */                (status != HTTP_NOT_MODIFIED)) { /* not 304 */               ap_discard_request_body(rp);           }            return status;        }    } else        return OK;}staticapr_status_t ap_proxy_http_cleanup(const char *scheme, request_rec *r,                                   proxy_conn_rec *backend){    ap_proxy_release_connection(scheme, backend, r->server);    return OK;}/* * This handles http:// URLs, and other URLs using a remote proxy over http * If proxyhost is NULL, then contact the server directly, otherwise * go via the proxy. * Note that if a proxy is used, then URLs other than http: can be accessed, * also, if we have trouble which is clearly specific to the proxy, then * we return DECLINED so that we can try another proxy. (Or the direct * route.) */static int proxy_http_handler(request_rec *r, proxy_worker *worker,                              proxy_server_conf *conf,                              char *url, const char *proxyname,                              apr_port_t proxyport){    int status;    char server_portstr[32];    char *scheme;    const char *proxy_function;    const char *u;    proxy_conn_rec *backend = NULL;    int is_ssl = 0;    /* Note: Memory pool allocation.     * A downstream keepalive connection is always connected to the existence     * (or not) of an upstream keepalive connection. If this is not done then     * load balancing against multiple backend servers breaks (one backend     * server ends up taking 100% of the load), and the risk is run of     * downstream keepalive connections being kept open unnecessarily. This     * keeps webservers busy and ties up resources.     *     * As a result, we allocate all sockets out of the upstream connection     * pool, and when we want to reuse a socket, we check first whether the     * connection ID of the current upstream connection is the same as that     * of the connection when the socket was opened.     */    apr_pool_t *p = r->connection->pool;    conn_rec *c = r->connection;    apr_uri_t *uri = apr_palloc(r->connection->pool, sizeof(*uri));    /* find the scheme */    u = strchr(url, ':');    if (u == NULL || u[1] != '/' || u[2] != '/' || u[3] == '\0')       return DECLINED;    if ((u - url) > 14)        return HTTP_BAD_REQUEST;    scheme = apr_pstrndup(c->pool, url, u - url);    /* scheme is lowercase */    ap_str_tolower(scheme);    /* is it for us? */    if (strcmp(scheme, "https") == 0) {        if (!ap_proxy_ssl_enable(NULL)) {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: HTTPS: declining URL %s"                         " (mod_ssl not configured?)", url);            return DECLINED;        }        is_ssl = 1;        proxy_function = "HTTPS";    }    else if (!(strcmp(scheme, "http") == 0 || (strcmp(scheme, "ftp") == 0 && proxyname))) {        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: HTTP: declining URL %s", url);        return DECLINED; /* only interested in HTTP, or FTP via proxy */    }    else {        if (*scheme == 'h')            proxy_function = "HTTP";        else            proxy_function = "FTP";    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,             "proxy: HTTP: serving URL %s", url);    /* create space for state information */    if ((status = ap_proxy_acquire_connection(proxy_function, &backend,                                              worker, r->server)) != OK)        goto cleanup;    backend->is_ssl = is_ssl;    /*     * TODO: Currently we cannot handle persist

⌨️ 快捷键说明

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