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

📄 proxy_http.c

📁 apache 安装教程 apache 安装教程
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* HTTP routines for Apache proxy */#include "mod_proxy.h"#include "http_log.h"#include "http_main.h"#include "http_core.h"#include "util_date.h"/* * Canonicalise http-like URLs. *  scheme is the scheme for the URL *  url    is the URL starting with the first '/' *  def_port is the default port for this scheme. */int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_port){    char *host, *path, *search, sport[7];    const char *err;    int port;    /*     * do syntatic check. We break the URL into host, port, path, search     */    port = def_port;    err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);    if (err)        return HTTP_BAD_REQUEST;    /* now parse path/search args, according to rfc1738 */    /*     * N.B. if this isn't a true proxy request, then the URL _path_ has     * already been decoded.  True proxy requests have r->uri ==     * r->unparsed_uri, and no others have that property.     */    if (r->uri == r->unparsed_uri) {        search = strchr(url, '?');        if (search != NULL)            *(search++) = '\0';    }    else        search = r->args;    /* process path */    path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path,                             r->proxyreq);    if (path == NULL)        return HTTP_BAD_REQUEST;    if (port != def_port)        ap_snprintf(sport, sizeof(sport), ":%d", port);    else        sport[0] = '\0';    r->filename = ap_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/",                   path, (search) ? "?" : "", (search) ? search : "", NULL);    return OK;}/* handle the conversion of URLs in the ProxyPassReverse function */static const char *proxy_location_reverse_map(request_rec *r, const char *url){    void *sconf;    proxy_server_conf *conf;    struct proxy_alias *ent;    int i, l1, l2;    char *u;    sconf = r->server->module_config;    conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);    l1 = strlen(url);    ent = (struct proxy_alias *)conf->raliases->elts;    for (i = 0; i < conf->raliases->nelts; i++) {        l2 = strlen(ent[i].real);        if (l1 >= l2 && strncmp(ent[i].real, url, l2) == 0) {            u = ap_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);            return ap_construct_url(r->pool, u, r);        }    }    return url;}/* * 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.) */int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url,                              const char *proxyhost, int proxyport){    const char *strp;    char *strp2;    const char *err, *desthost;    int i, j, sock,/* len,*/ backasswards;    table *req_hdrs, *resp_hdrs;    array_header *reqhdrs_arr;    table_entry *reqhdrs_elts;    struct sockaddr_in server;    struct in_addr destaddr;    struct hostent server_hp;    BUFF *f;    char buffer[HUGE_STRING_LEN];    char portstr[32];    pool *p = r->pool;    int destport = 0;    const char *chunked = NULL;    char *destportstr = NULL;    const char *urlptr = NULL;    const char *datestr, *urlstr;    int result, major, minor;    const char *content_length;    void *sconf = r->server->module_config;    proxy_server_conf *conf =    (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);    struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;    struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts;    int nocache = 0;    if (conf->cache.root == NULL)        nocache = 1;    memset(&server, '\0', sizeof(server));    server.sin_family = AF_INET;        /* We break the URL into host, port, path-search */    urlptr = strstr(url, "://");    if (urlptr == NULL)        return HTTP_BAD_REQUEST;    urlptr += 3;    destport = DEFAULT_HTTP_PORT;    strp = strchr(urlptr, '/');    if (strp == NULL) {        desthost = ap_pstrdup(p, urlptr);        urlptr = "/";    }    else {        char *q = ap_palloc(p, strp - urlptr + 1);        memcpy(q, urlptr, strp - urlptr);        q[strp - urlptr] = '\0';        urlptr = strp;        desthost = q;    }    strp2 = strchr(desthost, ':');    if (strp2 != NULL) {        *(strp2++) = '\0';        if (ap_isdigit(*strp2)) {            destport = atoi(strp2);            destportstr = strp2;        }    }    /* check if ProxyBlock directive on this host */    destaddr.s_addr = ap_inet_addr(desthost);    for (i = 0; i < conf->noproxies->nelts; i++) {        if (destaddr.s_addr == npent[i].addr.s_addr ||            (npent[i].name != NULL &&             (npent[i].name[0] == '*' || strstr(desthost, npent[i].name) != NULL)))            return ap_proxyerror(r, HTTP_FORBIDDEN,                                 "Connect to remote machine blocked");    }    if (proxyhost != NULL) {        server.sin_port = htons((unsigned short)proxyport);        err = ap_proxy_host2addr(proxyhost, &server_hp);        if (err != NULL)            return DECLINED;    /* try another */    }    else {        server.sin_port = htons((unsigned short)destport);        err = ap_proxy_host2addr(desthost, &server_hp);        if (err != NULL)            return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err);    }    /*     * we have worked out who exactly we are going to connect to, now make     * that connection...     */    sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);    if (sock == -1) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,                      "proxy: error creating socket");        return HTTP_INTERNAL_SERVER_ERROR;    }#if !defined(TPF) && !defined(BEOS)    if (conf->recv_buffer_size) {        if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,                       (const char *)&conf->recv_buffer_size, sizeof(int))            == -1) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, r,                          "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");        }    }#endif#ifdef SINIX_D_RESOLVER_BUG    {        struct in_addr *ip_addr = (struct in_addr *)*server_hp.h_addr_list;        for (; ip_addr->s_addr != 0; ++ip_addr) {            memcpy(&server.sin_addr, ip_addr, sizeof(struct in_addr));            i = ap_proxy_doconnect(sock, &server, r);            if (i == 0)                break;            /*             * Even if the connection was unsuccesful we should             * reinit the socket             */            sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);        }    }#else    j = 0;    while (server_hp.h_addr_list[j] != NULL) {        memcpy(&server.sin_addr, server_hp.h_addr_list[j],               sizeof(struct in_addr));        i = ap_proxy_doconnect(sock, &server, r);        if (i == 0)            break;        /*         * Even if the connection was unsuccesful we should         * reinit the socket         */        sock = ap_psocket_ex(p, PF_INET, SOCK_STREAM, IPPROTO_TCP, 1);        j++;    }#endif    if (i == -1) {        if (proxyhost != NULL)            return DECLINED;    /* try again another way */        else            return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool,                                    "Could not connect to remote machine: ",                                                    strerror(errno), NULL));    }    /* record request_time for HTTP/1.1 age calculation */    c->req_time = time(NULL);    /*     * build upstream-request headers by stripping r->headers_in from     * connection specific headers. We must not remove the Connection: header     * from r->headers_in, we still have to react to Connection: close     */    req_hdrs = ap_copy_table(r->pool, r->headers_in);    ap_proxy_clear_connection(r->pool, req_hdrs);    /*     * At this point, we start sending the HTTP/1.1 request to the remote     * server (proxy or otherwise).     */    f = ap_bcreate(p, B_RDWR | B_SOCKET);    ap_bpushfd(f, sock, sock);    ap_hard_timeout("proxy send", r);    ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.1" CRLF,              NULL);    /* Send Host: now, adding it to req_hdrs wouldn't be much better */    if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)        ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);    else        ap_bvputs(f, "Host: ", desthost, CRLF, NULL);    if (conf->viaopt == via_block) {        /* Block all outgoing Via: headers */        ap_table_unset(req_hdrs, "Via");    }    else if (conf->viaopt != via_off) {        /* Create a "Via:" request header entry and merge it */        i = ap_get_server_port(r);        if (ap_is_default_port(i, r)) {            strcpy(portstr, "");        }        else {            ap_snprintf(portstr, sizeof portstr, ":%d", i);        }        /* Generate outgoing Via: header with/without server comment: */        ap_table_mergen(req_hdrs, "Via",                        (conf->viaopt == via_full)                        ? ap_psprintf(p, "%d.%d %s%s (%s)",                                      HTTP_VERSION_MAJOR(r->proto_num),                                      HTTP_VERSION_MINOR(r->proto_num),                                      ap_get_server_name(r), portstr,                                      SERVER_BASEVERSION)                        : ap_psprintf(p, "%d.%d %s%s",                                      HTTP_VERSION_MAJOR(r->proto_num),                                      HTTP_VERSION_MINOR(r->proto_num),                                      ap_get_server_name(r), portstr)            );    }    /* the X-* headers are only added if we are a reverse     * proxy, otherwise we would be giving away private information.     */    if (r->proxyreq == PROXY_PASS) {        const char *buf;        /*         * Add X-Forwarded-For: so that the upstream has a chance to determine,         * where the original request came from.

⌨️ 快捷键说明

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