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

📄 proxy_http.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright 1999-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed 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"module AP_MODULE_DECLARE_DATA proxy_http_module;int ap_proxy_http_canon(request_rec *r, char *url);int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,                          char *url, const char *proxyname,                           apr_port_t proxyport);typedef struct {    const char     *name;    apr_port_t      port;    apr_sockaddr_t *addr;    apr_socket_t   *sock;    int             close;} proxy_http_conn_t;static apr_status_t ap_proxy_http_cleanup(request_rec *r,                                          proxy_http_conn_t *p_conn,                                          proxy_conn_rec *backend);/* * 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){    char *host, *path, *search, sport[7];    const char *err;    const char *scheme;    apr_port_t port, def_port;    /* ap_port_of_scheme() */    if (strncasecmp(url, "http:", 5) == 0) {        url += 5;        scheme = "http";    }    else if (strncasecmp(url, "https:", 6) == 0) {        url += 6;        scheme = "https";    }    else {        return DECLINED;    }    def_port = apr_uri_port_of_scheme(scheme);    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,             "proxy: HTTP: canonicalising URL %s", url);    /* 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) {        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                      "error parsing URL %s: %s",                      url, 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)        apr_snprintf(sport, sizeof(sport), ":%d", port);    else        sport[0] = '\0';    if (ap_strchr_c(host, ':')) { /* if literal IPv6 address */        host = apr_pstrcat(r->pool, "[", host, "]", NULL);    }    r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport,             "/", path, (search) ? "?" : "", (search) ? search : "", NULL);    return OK;} static const char *ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url){    struct proxy_alias *ent;    int i, l1, l2;    char *u;    /* XXX FIXME: Make sure this handled the ambiguous case of the :80     * after the hostname */    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 = apr_pstrcat(r->pool, ent[i].fake, &url[l2], NULL);            return ap_construct_url(r->pool, u, r);        }    }    return url;}/* Clear all connection-based headers from the incoming headers table */static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers){    const char *name;    char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));    apr_table_unset(headers, "Proxy-Connection");    if (!next)        return;    while (*next) {        name = next;        while (*next && !apr_isspace(*next) && (*next != ',')) {            ++next;        }        while (*next && (apr_isspace(*next) || (*next == ','))) {            *next = '\0';            ++next;        }        apr_table_unset(headers, name);    }    apr_table_unset(headers, "Connection");}staticapr_status_t ap_proxy_http_determine_connection(apr_pool_t *p, request_rec *r,                                                proxy_http_conn_t *p_conn,                                                conn_rec *c,                                                proxy_server_conf *conf,                                                apr_uri_t *uri,                                                char **url,                                                const char *proxyname,                                                apr_port_t proxyport,                                                char *server_portstr,                                                int server_portstr_size) {    int server_port;    apr_status_t err;    apr_sockaddr_t *uri_addr;    /*     * Break up the URL to determine the host to connect to     */    /* we break the URL into host, port, uri */    if (APR_SUCCESS != apr_uri_parse(p, *url, uri)) {        return ap_proxyerror(r, HTTP_BAD_REQUEST,                             apr_pstrcat(p,"URI cannot be parsed: ", *url,                                         NULL));    }    if (!uri->port) {        uri->port = apr_uri_port_of_scheme(uri->scheme);    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                 "proxy: HTTP connecting %s to %s:%d", *url, uri->hostname,                 uri->port);    /* do a DNS lookup for the destination host */    /* see memory note above */    err = apr_sockaddr_info_get(&uri_addr, apr_pstrdup(c->pool, uri->hostname),                                APR_UNSPEC, uri->port, 0, c->pool);    /* allocate these out of the connection pool - the check on     * r->connection->id makes sure that this string does not get accessed     * past the connection lifetime */    /* are we connecting directly, or via a proxy? */    if (proxyname) {        p_conn->name = apr_pstrdup(c->pool, proxyname);        p_conn->port = proxyport;        /* see memory note above */        err = apr_sockaddr_info_get(&p_conn->addr, p_conn->name, APR_UNSPEC,                                    p_conn->port, 0, c->pool);    } else {        p_conn->name = apr_pstrdup(c->pool, uri->hostname);        p_conn->port = uri->port;        p_conn->addr = uri_addr;        *url = apr_pstrcat(p, uri->path, uri->query ? "?" : "",                           uri->query ? uri->query : "",                           uri->fragment ? "#" : "",                           uri->fragment ? uri->fragment : "", NULL);    }    if (err != APR_SUCCESS) {        return ap_proxyerror(r, HTTP_BAD_GATEWAY,                             apr_pstrcat(p, "DNS lookup failure for: ",                                         p_conn->name, NULL));    }    /* Get the server port for the Via headers */    {        server_port = ap_get_server_port(r);        if (ap_is_default_port(server_port, r)) {            strcpy(server_portstr,"");        } else {            apr_snprintf(server_portstr, server_portstr_size, ":%d",                         server_port);        }    }    /* check if ProxyBlock directive on this host */    if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) {        return ap_proxyerror(r, HTTP_FORBIDDEN,                             "Connect to remote machine blocked");    }    return OK;}staticapr_status_t ap_proxy_http_create_connection(apr_pool_t *p, request_rec *r,                                             proxy_http_conn_t *p_conn,                                             conn_rec *c, conn_rec **origin,                                             proxy_conn_rec *backend,                                             proxy_server_conf *conf,                                             const char *proxyname) {    int failed=0, new=0;    apr_socket_t *client_socket = NULL;    /* We have determined who to connect to. Now make the connection, supporting     * a KeepAlive connection.     */    /* get all the possible IP addresses for the destname and loop through them     * until we get a successful connection     */    /* if a keepalive socket is already open, check whether it must stay     * open, or whether it should be closed and a new socket created.     */    /* see memory note above */    if (backend->connection) {        client_socket = ap_get_module_config(backend->connection->conn_config, &core_module);        if ((backend->connection->id == c->id) &&            (backend->port == p_conn->port) &&            (backend->hostname) &&            (!apr_strnatcasecmp(backend->hostname, p_conn->name))) {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: keepalive address match (keep original socket)");        } else {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: keepalive address mismatch / connection has"                         " changed (close old socket (%s/%s, %d/%d))",                          p_conn->name, backend->hostname, p_conn->port,                         backend->port);            apr_socket_close(client_socket);            backend->connection = NULL;        }    }    /* get a socket - either a keepalive one, or a new one */    new = 1;    if ((backend->connection) && (backend->connection->id == c->id)) {        apr_size_t buffer_len = 1;        char test_buffer[1];         apr_status_t socket_status;        apr_interval_time_t current_timeout;        /* use previous keepalive socket */        *origin = backend->connection;        p_conn->sock = client_socket;        new = 0;        /* save timeout */        apr_socket_timeout_get(p_conn->sock, &current_timeout);        /* set no timeout */        apr_socket_timeout_set(p_conn->sock, 0);        socket_status = apr_recv(p_conn->sock, test_buffer, &buffer_len);        /* put back old timeout */        apr_socket_timeout_set(p_conn->sock, current_timeout);        if ( APR_STATUS_IS_EOF(socket_status) ) {            ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL,                         "proxy: previous connection is closed, creating a new connection.");            new = 1;        }    }    if (new) {        int rc;        /* create a new socket */        backend->connection = NULL;        /*         * At this point we have a list of one or more IP addresses of         * the machine to connect to. If configured, reorder this         * list so that the "best candidate" is first try. "best         * candidate" could mean the least loaded server, the fastest         * responding server, whatever.         *         * For now we do nothing, ie we get DNS round robin.         * XXX FIXME         */        failed = ap_proxy_connect_to_backend(&p_conn->sock, "HTTP",                                             p_conn->addr, p_conn->name,                                             conf, r->server, c->pool);        /* handle a permanent error on the connect */        if (failed) {            if (proxyname) {                return DECLINED;            } else {                return HTTP_BAD_GATEWAY;            }        }        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: socket is connected");        /* the socket is now open, create a new backend server connection */        *origin = ap_run_create_connection(c->pool, r->server, p_conn->sock,                                           r->connection->id,                                           r->connection->sbh, c->bucket_alloc);        if (!*origin) {        /* the peer reset the connection already; ap_run_create_connection()          * closed the socket         */            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,                         r->server, "proxy: an error occurred creating a "                         "new connection to %pI (%s)", p_conn->addr,                         p_conn->name);            apr_socket_close(p_conn->sock);            return HTTP_INTERNAL_SERVER_ERROR;        }        backend->connection = *origin;        backend->hostname = apr_pstrdup(c->pool, p_conn->name);        backend->port = p_conn->port;        if (backend->is_ssl) {            if (!ap_proxy_ssl_enable(backend->connection)) {                ap_log_error(APLOG_MARK, APLOG_ERR, 0,                             r->server, "proxy: failed to enable ssl support "                             "for %pI (%s)", p_conn->addr, p_conn->name);                return HTTP_INTERNAL_SERVER_ERROR;            }        }        else {            ap_proxy_ssl_disable(backend->connection);        }        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "proxy: connection complete to %pI (%s)",                     p_conn->addr, p_conn->name);        /* set up the connection filters */        rc = ap_run_pre_connection(*origin, p_conn->sock);        if (rc != OK && rc != DONE) {            (*origin)->aborted = 1;            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: HTTP: pre_connection setup failed (%d)",                         rc);

⌨️ 快捷键说明

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