summaryrefslogtreecommitdiff
path: root/modules/proxy/mod_proxy_scgi.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/proxy/mod_proxy_scgi.c')
-rw-r--r--modules/proxy/mod_proxy_scgi.c82
1 files changed, 64 insertions, 18 deletions
diff --git a/modules/proxy/mod_proxy_scgi.c b/modules/proxy/mod_proxy_scgi.c
index f77a986e..cede817a 100644
--- a/modules/proxy/mod_proxy_scgi.c
+++ b/modules/proxy/mod_proxy_scgi.c
@@ -37,13 +37,13 @@
#include "util_script.h"
#include "mod_proxy.h"
+#include "scgi.h"
#define SCHEME "scgi"
#define PROXY_FUNCTION "SCGI"
#define SCGI_MAGIC "SCGI"
#define SCGI_PROTOCOL_VERSION "1"
-#define SCGI_DEFAULT_PORT (4000)
/* just protect from typos */
#define CONTENT_LENGTH "CONTENT_LENGTH"
@@ -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;
@@ -176,13 +178,15 @@ static int scgi_canon(request_rec *r, char *url)
{
char *host, sport[sizeof(":65535")];
const char *err, *path;
- apr_port_t port = SCGI_DEFAULT_PORT;
+ apr_port_t port, def_port;
if (strncasecmp(url, SCHEME "://", sizeof(SCHEME) + 2)) {
return DECLINED;
}
url += sizeof(SCHEME); /* Keep slashes */
+ port = def_port = SCGI_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, APLOGNO(00857)
@@ -190,7 +194,12 @@ static int scgi_canon(request_rec *r, char *url)
return HTTP_BAD_REQUEST;
}
- apr_snprintf(sport, sizeof(sport), ":%u", port);
+ if (port != def_port) {
+ apr_snprintf(sport, sizeof(sport), ":%u", port);
+ }
+ else {
+ sport[0] = '\0';
+ }
if (ap_strchr(host, ':')) { /* if literal IPv6 address */
host = apr_pstrcat(r->pool, "[", host, "]", NULL);
@@ -410,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,
@@ -424,8 +451,9 @@ static int pass_response(request_rec *r, proxy_conn_rec *conn)
}
}
- /* XXX: What could we do with that return code? */
- (void)ap_pass_brigade(r->output_filters, bb);
+ if (ap_pass_brigade(r->output_filters, bb)) {
+ return AP_FILTER_ERROR;
+ }
return OK;
}
@@ -481,7 +509,7 @@ static int scgi_request_status(int *status, request_rec *r)
*status = HTTP_INTERNAL_SERVER_ERROR;
return *status;
}
- } while(0);
+ } while (0);
return OK;
/* break; */
@@ -502,7 +530,7 @@ static int scgi_handler(request_rec *r, proxy_worker *worker,
int status;
proxy_conn_rec *backend = NULL;
apr_pool_t *p = r->pool;
- apr_uri_t *uri = apr_palloc(r->pool, sizeof(*uri));
+ apr_uri_t *uri;
char dummy;
if (strncasecmp(url, SCHEME "://", sizeof(SCHEME) + 2)) {
@@ -520,6 +548,7 @@ static int scgi_handler(request_rec *r, proxy_worker *worker,
backend->is_ssl = 0;
/* Step One: Determine Who To Connect To */
+ uri = apr_palloc(p, sizeof(*uri));
status = ap_proxy_determine_connection(p, r, conf, worker, backend,
uri, &url, proxyname, proxyport,
&dummy, 1);
@@ -557,8 +586,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;
}
@@ -569,7 +598,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;
@@ -594,16 +623,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}
};