diff options
Diffstat (limited to 'modules/proxy/mod_proxy_scgi.c')
-rw-r--r-- | modules/proxy/mod_proxy_scgi.c | 82 |
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} }; |