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

📄 mod_proxy_http.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 "ap_regex.h"module AP_MODULE_DECLARE_DATA proxy_http_module;static apr_status_t ap_proxy_http_cleanup(const char *scheme,                                          request_rec *r,                                          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. */static int proxy_http_canon(request_rec *r, char *url){    char *host, *path, sport[7];    char *search = NULL;    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:     * process the path.     *     * In a reverse proxy, our URL has been processed, so canonicalise     * unless proxy-nocanon is set to say it's raw     * In a forward proxy, we have and MUST NOT MANGLE the original.     */    switch (r->proxyreq) {    default: /* wtf are we doing here? */    case PROXYREQ_REVERSE:        if (apr_table_get(r->notes, "proxy-nocanon")) {            path = url;   /* this is the raw path */        }        else {            path = ap_proxy_canonenc(r->pool, url, strlen(url),                                     enc_path, 0, r->proxyreq);            search = r->args;        }        break;    case PROXYREQ_PROXY:        path = url;        break;    }    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;}/* Clear all connection-based headers from the incoming headers table */typedef struct header_dptr {    apr_pool_t *pool;    apr_table_t *table;    apr_time_t time;} header_dptr;static ap_regex_t *warn_rx;static int clean_warning_headers(void *data, const char *key, const char *val){    apr_table_t *headers = ((header_dptr*)data)->table;    apr_pool_t *pool = ((header_dptr*)data)->pool;    char *warning;    char *date;    apr_time_t warn_time;    const int nmatch = 3;    ap_regmatch_t pmatch[3];    if (headers == NULL) {        ((header_dptr*)data)->table = headers = apr_table_make(pool, 2);    }/* * Parse this, suckers! * *    Warning    = "Warning" ":" 1#warning-value * *    warning-value = warn-code SP warn-agent SP warn-text *                                             [SP warn-date] * *    warn-code  = 3DIGIT *    warn-agent = ( host [ ":" port ] ) | pseudonym *                    ; the name or pseudonym of the server adding *                    ; the Warning header, for use in debugging *    warn-text  = quoted-string *    warn-date  = <"> HTTP-date <"> * * Buggrit, use a bloomin' regexp! * (\d{3}\s+\S+\s+\".*?\"(\s+\"(.*?)\")?)  --> whole in $1, date in $3 */    while (!ap_regexec(warn_rx, val, nmatch, pmatch, 0)) {        warning = apr_pstrndup(pool, val+pmatch[0].rm_so,                               pmatch[0].rm_eo - pmatch[0].rm_so);        warn_time = 0;        if (pmatch[2].rm_eo > pmatch[2].rm_so) {            /* OK, we have a date here */            date = apr_pstrndup(pool, val+pmatch[2].rm_so,                                pmatch[2].rm_eo - pmatch[2].rm_so);            warn_time = apr_date_parse_http(date);        }        if (!warn_time || (warn_time == ((header_dptr*)data)->time)) {            apr_table_addn(headers, key, warning);        }        val += pmatch[0].rm_eo;    }    return 1;}static apr_table_t *ap_proxy_clean_warnings(apr_pool_t *p, apr_table_t *headers){   header_dptr x;   x.pool = p;   x.table = NULL;   x.time = apr_date_parse_http(apr_table_get(headers, "Date"));   apr_table_do(clean_warning_headers, &x, headers, "Warning", NULL);   if (x.table != NULL) {       apr_table_unset(headers, "Warning");       return apr_table_overlay(p, headers, x.table);   }   else {        return headers;   }}static int clear_conn_headers(void *data, const char *key, const char *val){    apr_table_t *headers = ((header_dptr*)data)->table;    apr_pool_t *pool = ((header_dptr*)data)->pool;    const char *name;    char *next = apr_pstrdup(pool, val);    while (*next) {        name = next;        while (*next && !apr_isspace(*next) && (*next != ',')) {            ++next;        }        while (*next && (apr_isspace(*next) || (*next == ','))) {            *next++ = '\0';        }        apr_table_unset(headers, name);    }    return 1;}static void ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers){    header_dptr x;    x.pool = p;    x.table = headers;    apr_table_unset(headers, "Proxy-Connection");    apr_table_do(clear_conn_headers, &x, headers, "Connection", NULL);    apr_table_unset(headers, "Connection");}static void add_te_chunked(apr_pool_t *p,                           apr_bucket_alloc_t *bucket_alloc,                           apr_bucket_brigade *header_brigade){    apr_bucket *e;    char *buf;    const char te_hdr[] = "Transfer-Encoding: chunked" CRLF;    buf = apr_pmemdup(p, te_hdr, sizeof(te_hdr)-1);    ap_xlate_proto_to_ascii(buf, sizeof(te_hdr)-1);    e = apr_bucket_pool_create(buf, sizeof(te_hdr)-1, p, bucket_alloc);    APR_BRIGADE_INSERT_TAIL(header_brigade, e);}static void add_cl(apr_pool_t *p,                   apr_bucket_alloc_t *bucket_alloc,                   apr_bucket_brigade *header_brigade,                   const char *cl_val){    apr_bucket *e;    char *buf;    buf = apr_pstrcat(p, "Content-Length: ",                      cl_val,                      CRLF,                      NULL);    ap_xlate_proto_to_ascii(buf, strlen(buf));    e = apr_bucket_pool_create(buf, strlen(buf), p, bucket_alloc);    APR_BRIGADE_INSERT_TAIL(header_brigade, e);}#define ASCII_CRLF  "\015\012"#define ASCII_ZERO  "\060"static void terminate_headers(apr_bucket_alloc_t *bucket_alloc,                              apr_bucket_brigade *header_brigade){    apr_bucket *e;    /* add empty line at the end of the headers */    e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);    APR_BRIGADE_INSERT_TAIL(header_brigade, e);}static int pass_brigade(apr_bucket_alloc_t *bucket_alloc,                                 request_rec *r, proxy_conn_rec *conn,                                 conn_rec *origin, apr_bucket_brigade *bb,                                 int flush){    apr_status_t status;    apr_off_t transferred;    if (flush) {        apr_bucket *e = apr_bucket_flush_create(bucket_alloc);        APR_BRIGADE_INSERT_TAIL(bb, e);    }    apr_brigade_length(bb, 0, &transferred);    if (transferred != -1)        conn->worker->s->transferred += transferred;    status = ap_pass_brigade(origin->output_filters, bb);    if (status != APR_SUCCESS) {        ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,                     "proxy: pass request body failed to %pI (%s)",                     conn->addr, conn->hostname);        if (origin->aborted) {             return APR_STATUS_IS_TIMEUP(status) ? HTTP_GATEWAY_TIME_OUT : HTTP_BAD_GATEWAY;        }        else {             return HTTP_BAD_REQUEST;         }    }    apr_brigade_cleanup(bb);    return OK;}#define MAX_MEM_SPOOL 16384static int stream_reqbody_chunked(apr_pool_t *p,                                           request_rec *r,                                           proxy_conn_rec *p_conn,                                           conn_rec *origin,                                           apr_bucket_brigade *header_brigade,                                           apr_bucket_brigade *input_brigade){    int seen_eos = 0, rv = OK;    apr_size_t hdr_len;    apr_off_t bytes;    apr_status_t status;    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;    apr_bucket_brigade *bb;    apr_bucket *e;    add_te_chunked(p, bucket_alloc, header_brigade);    terminate_headers(bucket_alloc, header_brigade);    while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))    {        char chunk_hdr[20];  /* must be here due to transient bucket. */        /* If this brigade contains EOS, either stop or remove it. */        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {            seen_eos = 1;            /* We can't pass this EOS to the output_filters. */            e = APR_BRIGADE_LAST(input_brigade);            apr_bucket_delete(e);        }        apr_brigade_length(input_brigade, 1, &bytes);        hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),                               "%" APR_UINT64_T_HEX_FMT CRLF,                               (apr_uint64_t)bytes);        ap_xlate_proto_to_ascii(chunk_hdr, hdr_len);        e = apr_bucket_transient_create(chunk_hdr, hdr_len,                                        bucket_alloc);        APR_BRIGADE_INSERT_HEAD(input_brigade, e);        /*         * Append the end-of-chunk CRLF         */        e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);        APR_BRIGADE_INSERT_TAIL(input_brigade, e);        if (header_brigade) {            /* we never sent the header brigade, so go ahead and

⌨️ 快捷键说明

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