From ba6157dcedae3c4d39d0170f1474d7665b0d6585 Mon Sep 17 00:00:00 2001
From: Jim Jagielski
Date: Thu, 7 May 2015 16:27:39 +0000
Subject: [PATCH] i ProxySCGIInternalRedirect with alternate response header
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1678234 13f79535-47bb-0310-9956-ffa450edef68
---
CHANGES | 5 +++
STATUS | 9 -----
docs/manual/mod/mod_proxy_scgi.xml | 18 ++++++---
modules/proxy/mod_proxy_scgi.c | 59 ++++++++++++++++++++++++------
4 files changed, 66 insertions(+), 25 deletions(-)
diff --git a/CHANGES b/CHANGES
index 9fce9fd4183..f22738d5339 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,6 +16,11 @@ Changes with Apache 2.4.13
rfc822Name and dNSName into SSL_{CLIENT,SERVER}_SAN_{Email,DNS}_n
environment variables. Also addresses PR 57207. [Kaspar Brand]
+ *) 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]
+
*) mpm_event: Allow for timer events duplicates. [Jim Jagielski, Yann Ylavic]
*) mod_proxy, mod_ssl, mod_cache_socache, mod_socache_*: Support machine
diff --git a/STATUS b/STATUS
index 135b91f000b..710c02865fe 100644
--- a/STATUS
+++ b/STATUS
@@ -105,15 +105,6 @@ RELEASE SHOWSTOPPERS:
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- *) mod_proxy_scgi: ProxySCGIInternalRedirect with alternate response header
- trunk patch: 1674510
- 2.4.x patch: trunk works (modulo CHANGES)
- This also needs in the doc moved down like in
- http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_proxy_scgi.xml?r1=1674510&r2=1674530&diff_format=h
- and the version edited :)
- Pre-edited: http://people.apache.org/~trawick/r1674510-to-2.4.x.txt
- +1: trawick, jim, ylavic
-
* mod_dav: Avoid some work that is unnecessary and often very time consuming.
This helps mitigate Subversion issue #4531:
http://subversion.tigris.org/issues/show_bug.cgi?id=4531
diff --git a/docs/manual/mod/mod_proxy_scgi.xml b/docs/manual/mod/mod_proxy_scgi.xml
index a5ebc7e7c76..79b4293c389 100644
--- a/docs/manual/mod/mod_proxy_scgi.xml
+++ b/docs/manual/mod/mod_proxy_scgi.xml
@@ -145,27 +145,35 @@ ProxySCGISendfile X-Send-Static
ProxySCGIInternalRedirect
Enable or disable internal redirect responses from the
backend
-ProxySCGIInternalRedirect On|Off
+ProxySCGIInternalRedirect On|Off|Headername
ProxySCGIInternalRedirect On
server configvirtual host
directory
+The Headername feature is available in version
+2.4.13 and later
The ProxySCGIInternalRedirect enables the 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 7fb2b873a96..4083b90fe1d 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,
@@ -564,8 +584,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;
}
@@ -576,7 +596,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;
@@ -601,16 +621,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.47.2