From c020c018654def84131dff2df9d5dc3a7e14921a Mon Sep 17 00:00:00 2001 From: Jeff Trawick Date: Sat, 18 Apr 2015 13:48:57 +0000 Subject: [PATCH] mod_proxy_scgi: ProxySCGIInternalRedirect now allows an alternate response header to be used by the application, for when the application or framework is unable to return Location in the internal-redirect form. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1674510 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 5 +++ docs/manual/mod/mod_proxy_scgi.xml | 18 ++++++--- modules/proxy/mod_proxy_scgi.c | 59 ++++++++++++++++++++++++------ 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index 5fa6cdff24..a94d77ca3e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_proxy_scgi: ProxySCGIInternalRedirect now allows an alternate + response header to be used by the application, for when the application + or framework is unable to return Location in the internal-redirect + form. [Jeff Trawick] + *) ssl: Add a warning if protocol given in SSLProtocol or SSLProxyProtocol will override other parameters given in the same directive. This could be a missing + or - prefix. PR 52820 [Christophe Jaillet] diff --git a/docs/manual/mod/mod_proxy_scgi.xml b/docs/manual/mod/mod_proxy_scgi.xml index 2e641dab74..c960bab9fc 100644 --- a/docs/manual/mod/mod_proxy_scgi.xml +++ b/docs/manual/mod/mod_proxy_scgi.xml @@ -144,8 +144,10 @@ ProxySCGISendfile X-Send-Static ProxySCGIInternalRedirect Enable or disable internal redirect responses from the backend -ProxySCGIInternalRedirect On|Off +ProxySCGIInternalRedirect On|Off|Headername ProxySCGIInternalRedirect On +The Headername feature is available in Apache +httpd 2.5.0 and later. server configvirtual host directory @@ -154,17 +156,23 @@ backend to internally redirect the gateway to a different URL. This feature originates in mod_cgi, which internally redirects the response if the response status is OK (200) and - the response contains a Location header and its value starts - with a slash (/). This value is interpreted as a new local - URL that Apache httpd internally redirects to.

+ the response contains a Location (or configured alternate + header) and its value starts with a slash (/). This value is + interpreted as a new local URL that Apache httpd internally redirects to.

mod_proxy_scgi does the same as mod_cgi in this regard, except that you can turn off the - feature.

+ feature or specify the use of a header other than Location.

Example ProxySCGIInternalRedirect Off + +# Django and some other frameworks will fully qualify "local URLs" +# set by the application, so an alternate header must be used. +<Location /django-app/> + ProxySCGIInternalRedirect X-Location +</Location> diff --git a/modules/proxy/mod_proxy_scgi.c b/modules/proxy/mod_proxy_scgi.c index 464a3bc355..2cbe8483f3 100644 --- a/modules/proxy/mod_proxy_scgi.c +++ b/modules/proxy/mod_proxy_scgi.c @@ -64,10 +64,12 @@ typedef struct { const char *scgi_sendfile_off = "off"; const char *scgi_sendfile_on = "X-Sendfile"; +const char *scgi_internal_redirect_off = "off"; +const char *scgi_internal_redirect_on = "Location"; typedef struct { const char *sendfile; - int internal_redirect; + const char *internal_redirect; } scgi_config; @@ -417,11 +419,29 @@ static int pass_response(request_rec *r, proxy_conn_rec *conn) } } - if (conf->internal_redirect && r->status == HTTP_OK) { - location = apr_table_get(r->headers_out, "Location"); + if (r->status == HTTP_OK + && (!conf->internal_redirect /* default === On */ + || conf->internal_redirect != scgi_internal_redirect_off)) { + short err = 1; + const char *location_header = conf->internal_redirect ? + conf->internal_redirect : scgi_internal_redirect_on; + + location = apr_table_get(r->err_headers_out, location_header); + if (!location) { + err = 0; + location = apr_table_get(r->headers_out, location_header); + } if (location && *location == '/') { scgi_request_config *req_conf = apr_palloc(r->pool, sizeof(*req_conf)); + if (strcasecmp(location_header, "Location")) { + if (err) { + apr_table_unset(r->err_headers_out, location_header); + } + else { + apr_table_unset(r->headers_out, location_header); + } + } req_conf->location = location; req_conf->type = scgi_internal_redirect; ap_set_module_config(r->request_config, &proxy_scgi_module, @@ -565,8 +585,8 @@ static void *create_scgi_config(apr_pool_t *p, char *dummy) { scgi_config *conf=apr_palloc(p, sizeof(*conf)); - conf->sendfile = NULL; - conf->internal_redirect = -1; + conf->sendfile = NULL; /* === default (off) */ + conf->internal_redirect = NULL; /* === default (on) */ return conf; } @@ -577,7 +597,7 @@ static void *merge_scgi_config(apr_pool_t *p, void *base_, void *add_) scgi_config *base=base_, *add=add_, *conf=apr_palloc(p, sizeof(*conf)); conf->sendfile = add->sendfile ? add->sendfile: base->sendfile; - conf->internal_redirect = (add->internal_redirect != -1) + conf->internal_redirect = add->internal_redirect ? add->internal_redirect : base->internal_redirect; return conf; @@ -602,16 +622,33 @@ static const char *scgi_set_send_file(cmd_parms *cmd, void *mconfig, } +static const char *scgi_set_internal_redirect(cmd_parms *cmd, void *mconfig, + const char *arg) +{ + scgi_config *conf = mconfig; + + if (!strcasecmp(arg, "Off")) { + conf->internal_redirect = scgi_internal_redirect_off; + } + else if (!strcasecmp(arg, "On")) { + conf->internal_redirect = scgi_internal_redirect_on; + } + else { + conf->internal_redirect = arg; + } + return NULL; +} + + static const command_rec scgi_cmds[] = { AP_INIT_TAKE1("ProxySCGISendfile", scgi_set_send_file, NULL, RSRC_CONF|ACCESS_CONF, - "The name of the X-Sendfile peudo response header or " + "The name of the X-Sendfile pseudo response header or " "On or Off"), - AP_INIT_FLAG("ProxySCGIInternalRedirect", ap_set_flag_slot, - (void*)APR_OFFSETOF(scgi_config, internal_redirect), - RSRC_CONF|ACCESS_CONF, - "Off if internal redirect responses should not be accepted"), + AP_INIT_TAKE1("ProxySCGIInternalRedirect", scgi_set_internal_redirect, NULL, + RSRC_CONF|ACCESS_CONF, + "The name of the pseudo response header or On or Off"), {NULL} }; -- 2.40.0