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

📄 http_filters.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 4 页
字号:
        /* no such thing as a response protocol */        return;    }    validate_status_line(r);    if (!r->status_line) {        r->status_line = ap_get_status_line(r->status);    }    /* Note that we must downgrade before checking for force responses. */    if (r->proto_num > HTTP_VERSION(1,0)        && apr_table_get(r->subprocess_env, "downgrade-1.0")) {        r->proto_num = HTTP_VERSION(1,0);    }    /* kludge around broken browsers when indicated by force-response-1.0     */    if (r->proto_num == HTTP_VERSION(1,0)        && apr_table_get(r->subprocess_env, "force-response-1.0")) {        *protocol = "HTTP/1.0";        r->connection->keepalive = AP_CONN_CLOSE;    }    else {        *protocol = AP_SERVER_PROTOCOL;    }}/* fill "bb" with a barebones/initial HTTP response header */static void basic_http_header(request_rec *r, apr_bucket_brigade *bb,                              const char *protocol){    char *date;    const char *server;    header_struct h;    struct iovec vec[4];    if (r->assbackwards) {        /* there are no headers to send */        return;    }    /* Output the HTTP/1.x Status-Line and the Date and Server fields */    vec[0].iov_base = (void *)protocol;    vec[0].iov_len  = strlen(protocol);    vec[1].iov_base = (void *)" ";    vec[1].iov_len  = sizeof(" ") - 1;    vec[2].iov_base = (void *)(r->status_line);    vec[2].iov_len  = strlen(r->status_line);    vec[3].iov_base = (void *)CRLF;    vec[3].iov_len  = sizeof(CRLF) - 1;#if APR_CHARSET_EBCDIC    {        char *tmp;        apr_size_t len;        tmp = apr_pstrcatv(r->pool, vec, 4, &len);        ap_xlate_proto_to_ascii(tmp, len);        apr_brigade_write(bb, NULL, NULL, tmp, len);    }#else    apr_brigade_writev(bb, NULL, NULL, vec, 4);#endif    h.pool = r->pool;    h.bb = bb;    /*     * keep the set-by-proxy server and date headers, otherwise     * generate a new server header / date header     */    if (r->proxyreq != PROXYREQ_NONE) {        const char *proxy_date;        proxy_date = apr_table_get(r->headers_out, "Date");        if (!proxy_date) {            /*             * proxy_date needs to be const. So use date for the creation of             * our own Date header and pass it over to proxy_date later to             * avoid a compiler warning.             */            date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);            ap_recent_rfc822_date(date, r->request_time);            proxy_date = date;        }        form_header_field(&h, "Date", proxy_date);        server = apr_table_get(r->headers_out, "Server");        if (server) {            form_header_field(&h, "Server", server);        }    }    else {        date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);        ap_recent_rfc822_date(date, r->request_time);        form_header_field(&h, "Date", date);        form_header_field(&h, "Server", ap_get_server_banner());    }    /* unset so we don't send them again */    apr_table_unset(r->headers_out, "Date");        /* Avoid bogosity */    apr_table_unset(r->headers_out, "Server");}AP_DECLARE(void) ap_basic_http_header(request_rec *r, apr_bucket_brigade *bb){    const char *protocol;    basic_http_header_check(r, &protocol);    basic_http_header(r, bb, protocol);}/* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2 * have a header parsing bug.  If the terminating \r\n occur starting * at offset 256, 257 or 258 of output then it will not properly parse * the headers.  Curiously it doesn't exhibit this problem at 512, 513. * We are guessing that this is because their initial read of a new request * uses a 256 byte buffer, and subsequent reads use a larger buffer. * So the problem might exist at different offsets as well. * * This should also work on keepalive connections assuming they use the * same small buffer for the first read of each new request. * * At any rate, we check the bytes written so far and, if we are about to * tickle the bug, we instead insert a bogus padding header.  Since the bug * manifests as a broken image in Navigator, users blame the server.  :( * It is more expensive to check the User-Agent than it is to just add the * bytes, so we haven't used the BrowserMatch feature here. */static void terminate_header(apr_bucket_brigade *bb){    char tmp[] = "X-Pad: avoid browser bug" CRLF;    char crlf[] = CRLF;    apr_off_t len;    apr_size_t buflen;    (void) apr_brigade_length(bb, 1, &len);    if (len >= 255 && len <= 257) {        buflen = strlen(tmp);        ap_xlate_proto_to_ascii(tmp, buflen);        apr_brigade_write(bb, NULL, NULL, tmp, buflen);    }    buflen = strlen(crlf);    ap_xlate_proto_to_ascii(crlf, buflen);    apr_brigade_write(bb, NULL, NULL, crlf, buflen);}AP_DECLARE_NONSTD(int) ap_send_http_trace(request_rec *r){    core_server_config *conf;    int rv;    apr_bucket_brigade *bb;    header_struct h;    apr_bucket *b;    int body;    char *bodyread = NULL, *bodyoff;    apr_size_t bodylen = 0;    apr_size_t bodybuf;    long res = -1; /* init to avoid gcc -Wall warning */    if (r->method_number != M_TRACE) {        return DECLINED;    }    /* Get the original request */    while (r->prev) {        r = r->prev;    }    conf = (core_server_config *)ap_get_module_config(r->server->module_config,                                                      &core_module);    if (conf->trace_enable == AP_TRACE_DISABLE) {        apr_table_setn(r->notes, "error-notes",                      "TRACE denied by server configuration");        return HTTP_METHOD_NOT_ALLOWED;    }    if (conf->trace_enable == AP_TRACE_EXTENDED)        /* XX should be = REQUEST_CHUNKED_PASS */        body = REQUEST_CHUNKED_DECHUNK;    else        body = REQUEST_NO_BODY;    if ((rv = ap_setup_client_block(r, body))) {        if (rv == HTTP_REQUEST_ENTITY_TOO_LARGE)            apr_table_setn(r->notes, "error-notes",                          "TRACE with a request body is not allowed");        return rv;    }    if (ap_should_client_block(r)) {        if (r->remaining > 0) {            if (r->remaining > 65536) {                apr_table_setn(r->notes, "error-notes",                       "Extended TRACE request bodies cannot exceed 64k\n");                return HTTP_REQUEST_ENTITY_TOO_LARGE;            }            /* always 32 extra bytes to catch chunk header exceptions */            bodybuf = (apr_size_t)r->remaining + 32;        }        else {            /* Add an extra 8192 for chunk headers */            bodybuf = 73730;        }        bodyoff = bodyread = apr_palloc(r->pool, bodybuf);        /* only while we have enough for a chunked header */        while ((!bodylen || bodybuf >= 32) &&               (res = ap_get_client_block(r, bodyoff, bodybuf)) > 0) {            bodylen += res;            bodybuf -= res;            bodyoff += res;        }        if (res > 0 && bodybuf < 32) {            /* discard_rest_of_request_body into our buffer */            while (ap_get_client_block(r, bodyread, bodylen) > 0)                ;            apr_table_setn(r->notes, "error-notes",                   "Extended TRACE request bodies cannot exceed 64k\n");            return HTTP_REQUEST_ENTITY_TOO_LARGE;        }        if (res < 0) {            return HTTP_BAD_REQUEST;        }    }    ap_set_content_type(r, "message/http");    /* Now we recreate the request, and echo it back */    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);#if APR_CHARSET_EBCDIC    {        char *tmp;        apr_size_t len;        len = strlen(r->the_request);        tmp = apr_pmemdup(r->pool, r->the_request, len);        ap_xlate_proto_to_ascii(tmp, len);        apr_brigade_putstrs(bb, NULL, NULL, tmp, CRLF_ASCII, NULL);    }#else    apr_brigade_putstrs(bb, NULL, NULL, r->the_request, CRLF, NULL);#endif    h.pool = r->pool;    h.bb = bb;    apr_table_do((int (*) (void *, const char *, const char *))                 form_header_field, (void *) &h, r->headers_in, NULL);    apr_brigade_puts(bb, NULL, NULL, CRLF_ASCII);    /* If configured to accept a body, echo the body */    if (bodylen) {        b = apr_bucket_pool_create(bodyread, bodylen,                                   r->pool, bb->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(bb, b);    }    ap_pass_brigade(r->output_filters,  bb);    return DONE;}typedef struct header_filter_ctx {    int headers_sent;} header_filter_ctx;AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,                                                           apr_bucket_brigade *b){    request_rec *r = f->r;    conn_rec *c = r->connection;    const char *clheader;    const char *protocol;    apr_bucket *e;    apr_bucket_brigade *b2;    header_struct h;    header_filter_ctx *ctx = f->ctx;    const char *ctype;    ap_bucket_error *eb = NULL;    AP_DEBUG_ASSERT(!r->main);    if (r->header_only) {        if (!ctx) {            ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx));        }        else if (ctx->headers_sent) {            apr_brigade_destroy(b);            return OK;        }    }    for (e = APR_BRIGADE_FIRST(b);         e != APR_BRIGADE_SENTINEL(b);         e = APR_BUCKET_NEXT(e))    {        if (AP_BUCKET_IS_ERROR(e) && !eb) {            eb = e->data;            continue;        }        /*         * If we see an EOC bucket it is a signal that we should get out         * of the way doing nothing.         */        if (AP_BUCKET_IS_EOC(e)) {            ap_remove_output_filter(f);            return ap_pass_brigade(f->next, b);        }    }    if (eb) {        int status;        status = eb->status;        apr_brigade_cleanup(b);        ap_die(status, r);        return AP_FILTER_ERROR;    }    if (r->assbackwards) {        r->sent_bodyct = 1;        ap_remove_output_filter(f);        return ap_pass_brigade(f->next, b);    }    /*     * Now that we are ready to send a response, we need to combine the two     * header field tables into a single table.  If we don't do this, our     * later attempts to set or unset a given fieldname might be bypassed.     */    if (!apr_is_empty_table(r->err_headers_out)) {        r->headers_out = apr_table_overlay(r->pool, r->err_headers_out,                                           r->headers_out);    }    /*     * Remove the 'Vary' header field if the client can't handle it.     * Since this will have nasty effects on HTTP/1.1 caches, force     * the response into HTTP/1.0 mode.     *     * Note: the force-response-1.0 should come before the call to     *       basic_http_header_check()     */    if (apr_table_get(r->subprocess_env, "force-no-vary") != NULL) {        apr_table_unset(r->headers_out, "Vary");        r->proto_num = HTTP_VERSION(1,0);        apr_table_set(r->subprocess_env, "force-response-1.0", "1");    }    else {        fixup_vary(r);    }    /*     * Now remove any ETag response header field if earlier processing     * says so (such as a 'FileETag None' directive).     */    if (apr_table_get(r->notes, "no-etag") != NULL) {        apr_table_unset(r->headers_out, "ETag");    }    /* determine the protocol and whether we should use keepalives. */    basic_http_header_check(r, &protocol);    ap_set_keepalive(r);    if (r->chunked) {        apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");        apr_table_unset(r->headers_out, "Content-Length");    }    ctype = ap_make_content_type(r, r->content_type);    if (strcasecmp(ctype, NO_CONTENT_TYPE)) {        apr_table_setn(r->headers_out, "Content-Type", ctype);    }    if (r->content_encoding) {        apr_table_setn(r->headers_out, "Content-Encoding",                       r->content_encoding);    }    if (!apr_is_empty_array(r->content_languages)) {        int i;        char *token;        char **languages = (char **)(r->content_languages->elts);        const char *field = apr_table_get(r->headers_out, "Content-Language");        while (field && (token = ap_get_list_item(r->pool, &field)) != NULL) {            for (i = 0; i < r->content_languages->nelts; ++i) {                if (!strcasecmp(token, languages[i]))                    break;            }            if (i == r->content_languages->nelts) {                *((char **) apr_array_push(r->content_languages)) = token;            }        }        field = apr_array_pstrcat(r->pool, r->content_languages, ',');        apr_table_setn(r->headers_out, "Content-Language", field);    }    /*     * Control cachability for non-cachable responses if not already set by     * some other part of the server configuration.     */    if (r->no_cache && !apr_table_get(r->headers_out, "Expires")) {        char *date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);        ap_recent_rfc822_date(date, r->request_time);        apr_table_addn(r->headers_out, "Expires", date);    }    /* This is a hack, but I can't find anyway around it.  The idea is that

⌨️ 快捷键说明

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