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

📄 proxy_http.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 3 页
字号:
                 * 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;            } else {                /* strip connection listed hop-by-hop headers from response */                const char *buf;                p_conn->close += ap_proxy_liststr(apr_table_get(r->headers_out,                                                                "Connection"),                                                  "close");                ap_proxy_clear_connection(p, r->headers_out);                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) {                /* 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),                                           ap_get_server_name(r),                                           server_portstr,                                           AP_SERVER_BASEVERSION)                                     : apr_psprintf(p, "%d.%d %s%s",                                           HTTP_VERSION_MAJOR(r->proto_num),                                           HTTP_VERSION_MINOR(r->proto_num),                                           ap_get_server_name(r),                                           server_portstr)                );            }            /* cancel keepalive if HTTP/1.0 or less */            if ((major < 1) || (minor < 1)) {                p_conn->close += 1;                origin->keepalive = AP_CONN_CLOSE;            }        } else {            /* an http/0.9 response */            backasswards = 1;            r->status = 200;            r->status_line = "200 OK";            p_conn->close += 1;        }        if ( r->status != HTTP_CONTINUE ) {            received_continue = 0;        } else {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL,                         "proxy: HTTP: received 100 CONTINUE");        }        /* we must accept 3 kinds of date, but generate only 1 kind of date */        {            const char *buf;            if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {                apr_table_set(r->headers_out, "Date",                              ap_proxy_date_canon(p, buf));            }            if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {                apr_table_set(r->headers_out, "Expires",                              ap_proxy_date_canon(p, buf));            }            if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {                apr_table_set(r->headers_out, "Last-Modified",                              ap_proxy_date_canon(p, buf));            }        }        /* munge the Location and URI response headers according to         * ProxyPassReverse         */        {            const char *buf;            if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {                apr_table_set(r->headers_out, "Location",                              ap_proxy_location_reverse_map(r, conf, buf));            }            if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {                apr_table_set(r->headers_out, "Content-Location",                              ap_proxy_location_reverse_map(r, conf, buf));            }            if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {                apr_table_set(r->headers_out, "URI",                              ap_proxy_location_reverse_map(r, conf, buf));            }        }        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? If so, send the extra data */        if (backasswards) {            apr_ssize_t cntr = 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 */            (r->status > 199) &&                   /* not any 1xx response */            (r->status != HTTP_NO_CONTENT) &&      /* not 204 */            (r->status != HTTP_RESET_CONTENT) &&   /* not 205 */            (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) || r->status < 400 ) {                /* read the body, pass it to the output filters */                int finish = FALSE;                while (ap_get_brigade(rp->input_filters,                                       bb,                                       AP_MODE_READBYTES,                                       APR_BLOCK_READ,                                       conf->io_buffer_size) == APR_SUCCESS) {#if DEBUGGING                    {                    apr_off_t readbytes;                    apr_brigade_length(bb, 0, &readbytes);                    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))) {                        /* if this is the last brigade, cleanup the                         * backend connection first to prevent the                         * backend server from hanging around waiting                         * for a slow client to eat these bytes                         */                        ap_proxy_http_cleanup(r, p_conn, backend);                        /* 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! */                        p_conn->close = 1;  /* this causes socket close below */                        finish = TRUE;                    }                    /* make sure we always clean up after ourselves */                    apr_brigade_cleanup(bb);                    /* if we are done, leave */                    if (TRUE == finish) {                        break;                    }                }            }            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: end body send");        } else {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "proxy: header only");        }    }    if ( conf->error_override ) {        /* the code above this checks for 'OK' which is what the hook expects */        if ( r->status == HTTP_OK )            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 > 199) && /* not any 1xx response */                (status != HTTP_NO_CONTENT) && /* not 204 */                (status != HTTP_RESET_CONTENT) && /* not 205 */                (status != HTTP_NOT_MODIFIED)) { /* not 304 */               ap_discard_request_body(rp);           }            return status;        }    } else         return OK;}staticapr_status_t ap_proxy_http_cleanup(request_rec *r, proxy_http_conn_t *p_conn,                                   proxy_conn_rec *backend) {    /* If there are no KeepAlives, or if the connection has been signalled     * to close, close the socket and clean up     */    /* if the connection is < HTTP/1.1, or Connection: close,     * we close the socket, otherwise we leave it open for KeepAlive support     */    if (p_conn->close || (r->proto_num < HTTP_VERSION(1,1))) {        if (p_conn->sock) {            apr_socket_close(p_conn->sock);            p_conn->sock = NULL;            backend->connection = NULL;        }    }    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.) */int ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,                          char *url, const char *proxyname,                           apr_port_t proxyport){    int status;    char server_portstr[32];    conn_rec *origin = NULL;    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_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);    apr_uri_t *uri = apr_palloc(r->connection->pool, sizeof(*uri));    proxy_http_conn_t *p_conn = apr_pcalloc(r->connection->pool,                                           sizeof(*p_conn));    /* is it for us? */    if (strncasecmp(url, "https:", 6) == 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;    }    else if (!(strncasecmp(url, "http:", 5)==0 || (strncasecmp(url, "ftp:", 4)==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 */    }    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,             "proxy: HTTP: serving URL %s", url);            /* only use stored info for top-level pages. Sub requests don't share      * in keepalives     */    if (!r->main) {        backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config,                                                      &proxy_http_module);    }    /* create space for state information */    if (!backend) {        backend = apr_pcalloc(c->pool, sizeof(proxy_conn_rec));        backend->connection = NULL;        backend->hostname = NULL;        backend->port = 0;        if (!r->main) {            ap_set_module_config(c->conn_config, &proxy_http_module, backend);        }    }    backend->is_ssl = is_ssl;    /* Step One: Determine Who To Connect To */    status = ap_proxy_http_determine_connection(p, r, p_conn, c, conf, uri,                                                &url, proxyname, proxyport,                                                server_portstr,                                                sizeof(server_portstr));    if ( status != OK ) {        return status;    }    /* Step Two: Make the Connection */    status = ap_proxy_http_create_connection(p, r, p_conn, c, &origin, backend,                                             conf, proxyname);    if ( status != OK ) {        return status;    }       /* Step Three: Send the Request */    status = ap_proxy_http_request(p, r, p_conn, origin, conf, uri, url, bb,                                   server_portstr);    if ( status != OK ) {        return status;    }    /* Step Four: Receive the Response */    status = ap_proxy_http_process_response(p, r, p_conn, origin, backend, conf,                                            bb, server_portstr);    if ( status != OK ) {        /* clean up even if there is an error */        ap_proxy_http_cleanup(r, p_conn, backend);        return status;    }    /* Step Five: Clean Up */    status = ap_proxy_http_cleanup(r, p_conn, backend);    if ( status != OK ) {        return status;    }    return OK;}static void ap_proxy_http_register_hook(apr_pool_t *p){    proxy_hook_scheme_handler(ap_proxy_http_handler, NULL, NULL, APR_HOOK_FIRST);    proxy_hook_canon_handler(ap_proxy_http_canon, NULL, NULL, APR_HOOK_FIRST);}module AP_MODULE_DECLARE_DATA proxy_http_module = {    STANDARD20_MODULE_STUFF,    NULL,              /* create per-directory config structure */    NULL,              /* merge per-directory config structures */    NULL,              /* create per-server config structure */    NULL,              /* merge per-server config structures */    NULL,              /* command apr_table_t */    ap_proxy_http_register_hook/* register hooks */};

⌨️ 快捷键说明

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