Return-Path: X-Original-To: apmail-httpd-dev-archive@www.apache.org Delivered-To: apmail-httpd-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id D3CE811F0D for ; Sun, 11 May 2014 16:35:35 +0000 (UTC) Received: (qmail 78235 invoked by uid 500); 11 May 2014 16:35:30 -0000 Delivered-To: apmail-httpd-dev-archive@httpd.apache.org Received: (qmail 78178 invoked by uid 500); 11 May 2014 16:35:30 -0000 Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list dev@httpd.apache.org Received: (qmail 78170 invoked by uid 99); 11 May 2014 16:35:30 -0000 Received: from Unknown (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 11 May 2014 16:35:30 +0000 X-ASF-Spam-Status: No, hits=-0.7 required=5.0 tests=RCVD_IN_DNSWL_LOW,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of ylavic.dev@gmail.com designates 209.85.213.173 as permitted sender) Received: from [209.85.213.173] (HELO mail-ig0-f173.google.com) (209.85.213.173) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 11 May 2014 16:35:25 +0000 Received: by mail-ig0-f173.google.com with SMTP id hn18so2943697igb.12 for ; Sun, 11 May 2014 09:35:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; bh=0ovcHXQmC26Aykzx1vJQkOR6HsP6OM+Du5nPiIgKH+Q=; b=Mu1bTUVk46GLPxuDPfmCysSgVtORNGq/JbtuADjbKirlVfHBfrG7Clia94WTlzBsPs BxnrJNvs6DeyuSe0TPRI8UXSPdeqaLpNzv/Ts0gwNGdEmtRJnzakCMONneN2vK1nfuYm qzj5oSRpwEBff65OMQKdDgFTKQbKN3C1w5PL6bYUskoWnW3/KyL7RNMQY7lN0O6DaP+M Kj63AuLFDHlqTBwewXvHesVxiR39T8INQfz+PgriFQ7t20jKd6Wbsbdn8YbIoX7EYZyD S5rt46qQOBg76I3gESYYY9mG9m7JQUPWPb1vi0p2OLxs28zYPj6R8guzHDQMwoyjULA+ I/1w== MIME-Version: 1.0 X-Received: by 10.50.62.51 with SMTP id v19mr34347246igr.21.1399826102292; Sun, 11 May 2014 09:35:02 -0700 (PDT) Received: by 10.42.174.132 with HTTP; Sun, 11 May 2014 09:35:02 -0700 (PDT) In-Reply-To: References: Date: Sun, 11 May 2014 18:35:02 +0200 Message-ID: Subject: Re: stop copying footers to r->headers_in? From: Yann Ylavic To: httpd Content-Type: text/plain; charset=UTF-8 X-Virus-Checked: Checked by ClamAV on apache.org On Fri, May 9, 2014 at 5:01 PM, Edward Lu wrote: > Here's a 2.2.x backport of Yann's patch with a directive, MergeTrailers, > added in to opt-in to the old behavior. By default, it doesn't merge the > trailers. I'm working on adding the capability to mod_log_config to log the > trailers, but I figured I'd post this patch first to get some review. > (paste from your patch with comments below) > > Index: modules/http/http_request.c > =================================================================== > --- modules/http/http_request.c (revision 1593540) > +++ modules/http/http_request.c (working copy) > @@ -384,8 +384,10 @@ > new->main = r->main; > > new->headers_in = r->headers_in; > + new->trailers_in = r->trailers_in; > new->headers_out = apr_table_make(r->pool, 12); > new->err_headers_out = r->err_headers_out; > + new->trailers_out = r->trailers_out; Here my patch used : new->trailers_out = apr_table_make(r->pool, 5); so to start internal redirect(s) with fresh new outgoing trailers. I think the previous body (if any) is likely to be consumed when ap_internal_redirect[_handler] is called. I don't know what's the correct thing to do, though, my understanding is that err_headers_out are preserved here because they may contain (set-)cookies or alike, but the final response will be the one of the redirect (headers and body, if any). > new->subprocess_env = rename_original_env(r->pool, r->subprocess_env); > new->notes = apr_table_make(r->pool, 5); > > @@ -495,6 +497,8 @@ > r->headers_out); > r->err_headers_out = apr_table_overlay(r->pool, rr->err_headers_out, > r->err_headers_out); > + r->err_headers_out = apr_table_overlay(r->pool, rr->trailers_out, > + r->trailers_out); Probably a typo here, should be r->trailers_out = .... Otherwise, I agree with Eric that ap_http_filter() should save and restore the request's status/headers/notes by default, and only merge the trailers if configured to. Restoring the status and notes (set before the body is read) seems unconditional to me. Something like the following patch (against 2.2.x), which also fixes/improves (compared to my previous patch) the unsetting of the "error-notes" before/after the call to ap_get_mime_headers(). Index: modules/http/http_filters.c =================================================================== --- modules/http/http_filters.c (revision 1593786) +++ modules/http/http_filters.c (working copy) @@ -403,13 +407,61 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bu } if (!ctx->remaining) { - /* Handle trailers by calling ap_get_mime_headers again! */ + /* Handle trailers by calling ap_get_mime_headers again, + * but preserve original status and incoming headers (unless + * MergeTrailers in on) by saving/restoring them before/after. + */ + const char *error_notes = NULL; + int saved_status = f->r->status; + apr_table_t *saved_headers_in = f->r->headers_in; + const char *saved_error_notes = apr_table_get(f->r->notes, + "error-notes"); + + f->r->status = HTTP_OK; + f->r->headers_in = f->r->trailers_in; + apr_table_clear(f->r->headers_in); + if (saved_error_notes) { + apr_table_unset(f->r->notes, "error-notes"); + } + ctx->state = BODY_NONE; ap_get_mime_headers(f->r); - e = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(b, e); - ctx->eos_sent = 1; - return APR_SUCCESS; + if (f->r->status == HTTP_OK) { + e = apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(b, e); + ctx->eos_sent = 1; + rv = APR_SUCCESS; + } + else { + error_notes = apr_table_get(f->r->notes, "error-notes"); + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, + "Error while reading HTTP trailer: %i%s%s", + f->r->status, error_notes ? ": " : "", + error_notes ? error_notes : ""); + rv = APR_EINVAL; + } + + /* By default, don't merge in the trailers + * (treat UNSET as DISABLE) */ + if (conf->merge_trailers != AP_MERGE_TRAILERS_ENABLE) { + f->r->headers_in = saved_headers_in; + } + else { + f->r->headers_in = apr_table_overlay(f->r->pool, + saved_headers_in, + f->r->headers_in); + apr_table_clear(f->r->trailers_in); + } + if (saved_error_notes) { + apr_table_setn(f->r->notes, "error-notes", + saved_error_notes); + } + else if (error_notes) { + apr_table_unset(f->r->notes, "error-notes"); + } + f->r->status = saved_status; + + return rv; } } } [END] Regards, Yann.