You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Alexei Kosut <ak...@nueva.pvt.k12.ca.us> on 1997/06/24 12:39:01 UTC

Regex mod_alias

I recall someone saying that 1.3 was open for new features, at least
of a relatively minor type, so I have one. It's something I've
regretted not putting in 1.2 for a while. When we first put the regex
library into Apache, we modified a few directives to make use of them
where it seemed like a good idea. <Directory>, for example. 

At the time, I also thought about modifying Alias and Redirect to also
make use of regexes. However, mod_rewrite was available, and chock
full of these sorts of features, and it seemed that adding the
complexity to mod_alias would make the server more bloated and slower,
and mod_rewrite does come with the distribution, and is there for
use. It seemed logical that people who needed more than mod_alias
provided could easily use mod_rewrite.

However, I now feel that this is not sufficient. Many people do not
use mod_rewrite. It is complex to use, especially in .htaccess
files. It is not part of the core server configuration, which means
that those who download binary releases will not get it (including
most NT users). Even if it is installed, it can be daunting to
understand. Although very powerful and handy, it has been compared to
sendmail.cf.

This leaves Alias and Redirect underpowered. They can only match a
URL, and direct it and everything below it, keeping the extra path
information. They can't even handle simple, and oft-needed, chores
like "redirect this entire directly to this one file," or  "redirect
this directory to somewhere else, but not the files underneath it."

So I've created the below patch. It adds to Alias, ScriptAlias and
Redirect the ability to make use of regular expressions. The form is
based on that already used for <Directory>. The regex version of this
old favorite:

Alias /icons /usr/local/etc/httpd/icons

is

Alias ~ ^/icons(.*) /usr/local/etc/httpd/icons$1

Simple enough. It can't do anything much more complex than that, but
this is enough for most people. If they really need more, then
mod_rewrite is probably the right tool. And it does not slow the
server down if not used; it only adds one equality check to each time
an Alias entry is scanned. Hardly an important slowdown.

And it doesn't make mod_alias appreciably larger. It only adds a
couple of lines of code. I think it's worth including in 1.3.

Index: mod_alias.c
===================================================================
RCS file: /export/home/cvs/apache/src/mod_alias.c,v
retrieving revision 1.16
diff -c -r1.16 mod_alias.c
*** mod_alias.c	1997/06/15 19:22:28	1.16
--- mod_alias.c	1997/06/24 10:25:41
***************
*** 65,70 ****
--- 65,71 ----
      char *real;
      char *fake;
      char *handler;
+     regex_t *regexp;
      int redir_status;		/* 301, 302, 303, 410, etc */
  } alias_entry;
  
***************
*** 117,123 ****
      return a;
  }
  
! const char *add_alias(cmd_parms *cmd, void *dummy, char *f, char *r)
  {
      server_rec *s = cmd->server;
      alias_server_conf *conf =
--- 118,124 ----
      return a;
  }
  
! const char *add_alias(cmd_parms *cmd, void *dummy, char *f, char *r, char *e)
  {
      server_rec *s = cmd->server;
      alias_server_conf *conf =
***************
*** 126,132 ****
  
      /* XX r can NOT be relative to DocumentRoot here... compat bug. */
      
!     new->fake = f; new->real = r; new->handler = cmd->info;
      return NULL;
  }
  
--- 127,142 ----
  
      /* XX r can NOT be relative to DocumentRoot here... compat bug. */
      
!     if (e && !strcmp(f, "~")) {
! 	new->regexp = pregcomp(cmd->pool, r, REG_EXTENDED);
! 	if (new->regexp == NULL)
! 	    return "Regular expression could not be compiled.";
! 	new->fake = r; new->real = e; new->handler = cmd->info;
!     }
!     else {
! 	new->fake = f; new->real = r; new->handler = cmd->info;
!     }
! 
      return NULL;
  }
  
***************
*** 138,146 ****
--- 148,165 ----
      alias_server_conf *serverconf =
          (alias_server_conf *)get_module_config(s->module_config,&alias_module);
      int status = (int)cmd->info;
+     regex_t *r = NULL;
      char *f = arg2;
      char *url = arg3;
  
+     if (arg1[0] == '~' && arg3) {
+         r = pregcomp(cmd->pool, arg2, REG_EXTENDED);
+         if (r == NULL)
+             return "Regular expression could not be compiled.";
+ 
+ 	arg1++;
+     }
+ 
      if (!strcasecmp(arg1, "gone"))
  	status = HTTP_GONE;
      else if (!strcasecmp(arg1, "permanent"))
***************
*** 151,157 ****
  	status = HTTP_SEE_OTHER;
      else if (isdigit(*arg1))
  	status = atoi(arg1);
!     else {
  	f = arg1;
  	url = arg2;
      }
--- 170,176 ----
  	status = HTTP_SEE_OTHER;
      else if (isdigit(*arg1))
  	status = atoi(arg1);
!     else if (!arg3) {
  	f = arg1;
  	url = arg2;
      }
***************
*** 169,183 ****
      else
          new = push_array (serverconf->redirects);
  
!     new->fake = f; new->real = url;
      new->redir_status = status;
      return NULL;
  }
  
  command_rec alias_cmds[] = {
! { "Alias", add_alias, NULL, RSRC_CONF, TAKE2, 
      "a fakename and a realname"},
! { "ScriptAlias", add_alias, "cgi-script", RSRC_CONF, TAKE2, 
      "a fakename and a realname"},
  { "Redirect", add_redirect, (void*)HTTP_MOVED_TEMPORARILY, 
      OR_FILEINFO, TAKE23, 
--- 188,202 ----
      else
          new = push_array (serverconf->redirects);
  
!     new->fake = f; new->real = url; new->regexp = r;
      new->redir_status = status;
      return NULL;
  }
  
  command_rec alias_cmds[] = {
! { "Alias", add_alias, NULL, RSRC_CONF, TAKE23, 
      "a fakename and a realname"},
! { "ScriptAlias", add_alias, "cgi-script", RSRC_CONF, TAKE23, 
      "a fakename and a realname"},
  { "Redirect", add_redirect, (void*)HTTP_MOVED_TEMPORARILY, 
      OR_FILEINFO, TAKE23, 
***************
*** 228,255 ****
  char *try_alias_list (request_rec *r, array_header *aliases, int doesc, int *status)
  {
      alias_entry *entries = (alias_entry *)aliases->elts;
      int i;
      
      for (i = 0; i < aliases->nelts; ++i) {
          alias_entry *p = &entries[i];
!         int l = alias_matches (r->uri, p->fake);
  
!         if (l > 0) {
  	    if (p->handler) { /* Set handler, and leave a note for mod_cgi */
! 	        r->handler = pstrdup(r->pool, p->handler);
  		table_set (r->notes, "alias-forced-type", p->handler);
  	    }
! 
  	    *status = p->redir_status;
  
! 	    if (doesc) {
! 		char *escurl;
! 		escurl = os_escape_path(r->pool, r->uri + l, 1);
! 
! 		return pstrcat(r->pool, p->real, escurl, NULL);
! 	    } else
! 		return pstrcat(r->pool, p->real, r->uri + l, NULL);
!         }
      }
  
      return NULL;
--- 247,290 ----
  char *try_alias_list (request_rec *r, array_header *aliases, int doesc, int *status)
  {
      alias_entry *entries = (alias_entry *)aliases->elts;
+     regmatch_t regm[10];
+     char *found = NULL;
      int i;
      
      for (i = 0; i < aliases->nelts; ++i) {
          alias_entry *p = &entries[i];
! 	int l;
  
! 	if (p->regexp) {
! 	    if (!regexec(p->regexp, r->uri, p->regexp->re_nsub+1, regm, 0))
! 		found = pregsub(r->pool, p->real, r->uri,
! 				p->regexp->re_nsub+1, regm);
! 	}
! 	else {
! 	    l = alias_matches (r->uri, p->fake);
! 
! 	    if (l > 0) {
! 		if (doesc) {
! 		    char *escurl;
! 		    escurl = os_escape_path(r->pool, r->uri + l, 1);
! 		    
! 		    found = pstrcat(r->pool, p->real, escurl, NULL);
! 		} else
! 		    found = pstrcat(r->pool, p->real, r->uri + l, NULL);
! 	    }
! 	}
! 
! 	if (found) {
  	    if (p->handler) { /* Set handler, and leave a note for mod_cgi */
! 		r->handler = pstrdup(r->pool, p->handler);
  		table_set (r->notes, "alias-forced-type", p->handler);
  	    }
! 	    
  	    *status = p->redir_status;
  
! 	    return found;
! 	}
! 	
      }
  
      return NULL;


--  
________________________________________________________________________
Alexei Kosut <ak...@nueva.pvt.k12.ca.us>      The Apache HTTP Server
URL: http://www.nueva.pvt.k12.ca.us/~akosut/   http://www.apache.org/