Hi Eric, Looking at this feature, and the new allowance effective June 2014, is this something we would want to toggle by envvar (in addition to or in lieu of a directive) similar to various gzip, caching, downgrade and particularly the redirect-carefully overrides? This seems like the sort of feature to dodge for older unsuspecting clients based on browsermatch, once the exceptions are identified;
https://httpd.apache.org/docs/2.4/env.html#special On Mon, Jun 17, 2019 at 1:35 PM <cove...@apache.org> wrote: > Author: covener > Date: Mon Jun 17 18:35:24 2019 > New Revision: 1861542 > > URL: http://svn.apache.org/viewvc?rev=1861542&view=rev > Log: > add RedirectRelative directive to allow relative Redirect targets > > 2616 forbade relative redirect URLs, but 7231 allows them > Early 2.2 maintenance levels did not fix them up, but later 2.2 and all 2.4 > fixed them up with ap_construct_url(). > > Allow opt-in to not fixing up relative URLs with RedirectRelative > > > > Modified: > httpd/httpd/trunk/docs/manual/mod/mod_alias.xml > httpd/httpd/trunk/modules/mappers/mod_alias.c > > Modified: httpd/httpd/trunk/docs/manual/mod/mod_alias.xml > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_alias.xml?rev=1861542&r1=1861541&r2=1861542&view=diff > > ============================================================================== > --- httpd/httpd/trunk/docs/manual/mod/mod_alias.xml (original) > +++ httpd/httpd/trunk/docs/manual/mod/mod_alias.xml Mon Jun 17 18:35:24 > 2019 > @@ -621,4 +621,25 @@ ScriptAliasMatch "(?i)^/cgi-bin(.*)" "/u > </usage> > </directivesynopsis> > > +<directivesynopsis> > +<name>RedirectRelative</name> > +<description>Allows relative redirect targets.</description> > +<syntax>RedirectRelative OFF|ON</syntax> > +<default>RedirectRelative OFF</default> > +<contextlist><context>server config</context><context>virtual > host</context> > +<context>directory</context> > +<compatibility>2.5.1 and later</compatibility> > +</contextlist> > + > +<usage> > + <p>By default, if the target URL of a <directive>Redirect</directive> > + directive is a relative URL beginning with a '/' character, the > server > + converts it to a an absolute URL before responding to the client. By > + setting <directive>RedirectRelative</directive> to the value "ON", > + the relative URL is presented to the client directly.</p> > + > +</usage> > +</directivesynopsis> > + > + > </modulesynopsis> > > Modified: httpd/httpd/trunk/modules/mappers/mod_alias.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mappers/mod_alias.c?rev=1861542&r1=1861541&r2=1861542&view=diff > > ============================================================================== > --- httpd/httpd/trunk/modules/mappers/mod_alias.c (original) > +++ httpd/httpd/trunk/modules/mappers/mod_alias.c Mon Jun 17 18:35:24 2019 > @@ -37,6 +37,10 @@ > #include "ap_expr.h" > > > +#define ALIAS_FLAG_DEFAULT -1 > +#define ALIAS_FLAG_OFF 0 > +#define ALIAS_FLAG_ON 1 > + > typedef struct { > const char *real; > const char *fake; > @@ -58,6 +62,7 @@ typedef struct { > char *handler; > const ap_expr_info_t *redirect; > int redirect_status; /* 301, 302, 303, 410, etc */ > + int allow_relative; /* skip ap_construct_url() */ > } alias_dir_conf; > > module AP_MODULE_DECLARE_DATA alias_module; > @@ -80,6 +85,7 @@ static void *create_alias_dir_config(apr > alias_dir_conf *a = > (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf)); > a->redirects = apr_array_make(p, 2, sizeof(alias_entry)); > + a->allow_relative = ALIAS_FLAG_DEFAULT; > return a; > } > > @@ -111,7 +117,9 @@ static void *merge_alias_dir_config(apr_ > a->redirect = (overrides->redirect_set == 0) ? base->redirect : > overrides->redirect; > a->redirect_status = (overrides->redirect_set == 0) ? > base->redirect_status : overrides->redirect_status; > a->redirect_set = overrides->redirect_set || base->redirect_set; > - > + a->allow_relative = (overrides->allow_relative != ALIAS_FLAG_DEFAULT) > + ? overrides->allow_relative > + : base->allow_relative; > return a; > } > > @@ -591,31 +599,33 @@ static int translate_alias_redir(request > if (ret == PREGSUB_ERROR) > return HTTP_INTERNAL_SERVER_ERROR; > if (ap_is_HTTP_REDIRECT(status)) { > - if (ret[0] == '/') { > - char *orig_target = ret; > - > - ret = ap_construct_url(r->pool, ret, r); > - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > APLOGNO(00673) > - "incomplete redirection target of '%s' for " > - "URI '%s' modified to '%s'", > - orig_target, r->uri, ret); > - } > - if (!ap_is_url(ret)) { > - status = HTTP_INTERNAL_SERVER_ERROR; > - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00674) > - "cannot redirect '%s' to '%s'; " > - "target is not a valid absoluteURI or > abs_path", > - r->uri, ret); > - } > - else { > - /* append requested query only, if the config didn't > - * supply its own. > - */ > - if (r->args && !ap_strchr(ret, '?')) { > - ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL); > + alias_dir_conf *dirconf = (alias_dir_conf *) > + ap_get_module_config(r->per_dir_config, &alias_module); > + if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] != > '/') { > + if (ret[0] == '/') { > + char *orig_target = ret; > + > + ret = ap_construct_url(r->pool, ret, r); > + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > APLOGNO(00673) > + "incomplete redirection target of '%s' > for " > + "URI '%s' modified to '%s'", > + orig_target, r->uri, ret); > } > - apr_table_setn(r->headers_out, "Location", ret); > + if (!ap_is_url(ret)) { > + status = HTTP_INTERNAL_SERVER_ERROR; > + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, > APLOGNO(00674) > + "cannot redirect '%s' to '%s'; " > + "target is not a valid absoluteURI or > abs_path", > + r->uri, ret); > + } > + } > + /* append requested query only, if the config didn't > + * supply its own. > + */ > + if (r->args && !ap_strchr(ret, '?')) { > + ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL); > } > + apr_table_setn(r->headers_out, "Location", ret); > } > return status; > } > @@ -646,31 +656,31 @@ static int fixup_redir(request_rec *r) > if (ret == PREGSUB_ERROR) > return HTTP_INTERNAL_SERVER_ERROR; > if (ap_is_HTTP_REDIRECT(status)) { > - if (ret[0] == '/') { > - char *orig_target = ret; > - > - ret = ap_construct_url(r->pool, ret, r); > - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > APLOGNO(00675) > - "incomplete redirection target of '%s' for " > - "URI '%s' modified to '%s'", > - orig_target, r->uri, ret); > - } > - if (!ap_is_url(ret)) { > - status = HTTP_INTERNAL_SERVER_ERROR; > - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00676) > - "cannot redirect '%s' to '%s'; " > - "target is not a valid absoluteURI or > abs_path", > - r->uri, ret); > - } > - else { > - /* append requested query only, if the config didn't > - * supply its own. > - */ > - if (r->args && !ap_strchr(ret, '?')) { > - ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL); > + if (dirconf->allow_relative != ALIAS_FLAG_ON || ret[0] != > '/') { > + if (ret[0] == '/') { > + char *orig_target = ret; > + > + ret = ap_construct_url(r->pool, ret, r); > + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, > APLOGNO(00675) > + "incomplete redirection target of '%s' > for " > + "URI '%s' modified to '%s'", > + orig_target, r->uri, ret); > + } > + if (!ap_is_url(ret)) { > + status = HTTP_INTERNAL_SERVER_ERROR; > + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, > APLOGNO(00676) > + "cannot redirect '%s' to '%s'; " > + "target is not a valid absoluteURI or > abs_path", > + r->uri, ret); > } > - apr_table_setn(r->headers_out, "Location", ret); > } > + /* append requested query only, if the config didn't > + * supply its own. > + */ > + if (r->args && !ap_strchr(ret, '?')) { > + ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL); > + } > + apr_table_setn(r->headers_out, "Location", ret); > } > return status; > } > @@ -702,6 +712,10 @@ static const command_rec alias_cmds[] = > AP_INIT_TAKE2("RedirectPermanent", add_redirect2, > (void *) HTTP_MOVED_PERMANENTLY, OR_FILEINFO, > "a document to be redirected, then the destination > URL"), > + AP_INIT_FLAG("RedirectRelative", ap_set_flag_slot, > + (void*)APR_OFFSETOF(alias_dir_conf, allow_relative), > OR_FILEINFO, > + "Set to ON to allow relative redirect targets to be > issued as-is"), > + > {NULL} > }; > > > >