You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Ralf S. Engelschall" <rs...@engelschall.com> on 1998/02/12 16:18:56 UTC
[PATCH] New RewriteMap types for mod_rewrite
Apache as a Reverse Proxy and
Apache does Virtual Hosting without <VirtualHost>
-------------------------------------------------
The following patch superseeds the recently posted patch which just introduced
the int:toupper and int:tolower RewriteMap types, because for Reverse Proxing
a rnd:<file> type was needed and both patches change the same source part.
What it does:
- adds another new RewriteMap type rnd:<file> which is
equivalent to the txt:<file> type but with a special
post-processing for the looked up value: It is parsed into
alternatives according to "|" chars and then a particular
alternative is choosen randomly. This is an essential
functionality needed for balancing between backend-servers
when using Apache as a Reverse Proxy. The looked up value
here is a list of servers.
It is used like this:
RewriteMap server rnd:/u/rse/work/wt/ap/apache-rproxy.tab
RewriteRule ^/(.*\.(phtml|cgi))$ http://${server:dynamic}/$1 [P,L]
RewriteRule ^/(.*)$ http://${server:static}/$1 [P,L]
with /u/rse/work/wt/ap/apache-rproxy.tab reading:
static server1|server2|server3|server4
dynamic server5|server6
(The complete setup which is needed to let Apache act as a full-featured
Reverse Proxy is also available, but because I've developed it for an
WEBTechniques article I cannot publically post it here. When someone is
interested, I can post it to apache-core of course.)
- adds int:tolower and int:toupper Internal Function based
rewriting maps which can be used to map hostnames to a fixed
case when using mod_rewrite to do mass virtual hosting
without using 1001 <VirtualHost> section.
Greetings,
Ralf S. Engelschall
rse@engelschall.com
www.engelschall.com
Index: src/modules/standard/mod_rewrite.c
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/modules/standard/mod_rewrite.c,v
retrieving revision 1.66
diff -u -r1.66 mod_rewrite.c
--- mod_rewrite.c 1998/02/02 22:33:40 1.66
+++ mod_rewrite.c 1998/02/12 14:31:04
@@ -93,6 +93,7 @@
#include <time.h>
#include <signal.h>
#include <errno.h>
+#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef WIN32
@@ -435,11 +436,17 @@
new = push_array(sconf->rewritemaps);
new->name = a1;
+ new->func = NULL;
if (strncmp(a2, "txt:", 4) == 0) {
new->type = MAPTYPE_TXT;
new->datafile = a2+4;
new->checkfile = a2+4;
}
+ else if (strncmp(a2, "rnd:", 4) == 0) {
+ new->type = MAPTYPE_RND;
+ new->datafile = a2+4;
+ new->checkfile = a2+4;
+ }
else if (strncmp(a2, "dbm:", 4) == 0) {
#ifdef HAS_NDBM_LIB
new->type = MAPTYPE_DBM;
@@ -455,6 +462,18 @@
new->datafile = a2+4;
new->checkfile = a2+4;
}
+ else if (strncmp(a2, "int:", 4) == 0) {
+ new->type = MAPTYPE_INT;
+ new->datafile = NULL;
+ new->checkfile = NULL;
+ if (strcmp(a2+4, "tolower") == 0)
+ new->func = rewrite_mapfunc_tolower;
+ else if (strcmp(a2+4, "toupper") == 0)
+ new->func = rewrite_mapfunc_toupper;
+ else if (sconf->state == ENGINE_ENABLED)
+ return pstrcat(cmd->pool, "RewriteMap: internal map not found:",
+ a2+4, NULL);
+ }
else {
new->type = MAPTYPE_TXT;
new->datafile = a2;
@@ -2499,6 +2518,52 @@
s->name, key);
}
}
+ else if (s->type == MAPTYPE_INT) {
+ if ((value = lookup_map_internal(r, s->func, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
+ s->name, key, value);
+ return value;
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s key=%s",
+ s->name, key);
+ }
+ }
+ else if (s->type == MAPTYPE_RND) {
+ if (stat(s->checkfile, &st) == -1) {
+ aplog_error(APLOG_MARK, APLOG_ERR, r->server,
+ "mod_rewrite: can't access text RewriteMap "
+ "file %s", s->checkfile);
+ rewritelog(r, 1,
+ "can't open RewriteMap file, see error log");
+ return NULL;
+ }
+ value = get_cache_string(cachep, s->name, CACHEMODE_TS,
+ st.st_mtime, key);
+ if (value == NULL) {
+ rewritelog(r, 6, "cache lookup FAILED, forcing new "
+ "map lookup");
+ if ((value =
+ lookup_map_txtfile(r, s->datafile, key)) != NULL) {
+ rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] "
+ "-> val=%s", s->name, key, value);
+ set_cache_string(cachep, s->name, CACHEMODE_TS,
+ st.st_mtime, key, value);
+ }
+ else {
+ rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
+ "key=%s", s->name, key);
+ return NULL;
+ }
+ }
+ else {
+ rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s "
+ "-> val=%s", s->name, key, value);
+ }
+ value = select_random_value_part(r, value);
+ rewritelog(r, 5, "randomly choosen the subvalue `%s'", value);
+ return value;
+ }
}
}
return NULL;
@@ -2605,7 +2670,87 @@
return pstrdup(r->pool, buf);
}
+static char *lookup_map_internal(request_rec *r,
+ char *(*func)(request_rec *, char *),
+ char *key)
+{
+ /* currently we just let the function convert
+ the key to a corresponding value */
+ return func(r, key);
+}
+
+static char *rewrite_mapfunc_toupper(request_rec *r, char *key)
+{
+ char *value, *cp;
+
+ for (cp = value = pstrdup(r->pool, key); cp != NULL && *cp != '\0'; cp++)
+ *cp = toupper(*cp);
+ return value;
+}
+
+static char *rewrite_mapfunc_tolower(request_rec *r, char *key)
+{
+ char *value, *cp;
+
+ for (cp = value = pstrdup(r->pool, key); cp != NULL && *cp != '\0'; cp++)
+ *cp = tolower(*cp);
+ return value;
+}
+
+static int rewrite_rand_init_done = 0;
+void rewrite_rand_init(void)
+{
+ if (!rewrite_rand_init_done) {
+ srand((unsigned)(getpid()));
+ rewrite_rand_init_done = 1;
+ }
+ return;
+}
+
+int rewrite_rand(int l, int h)
+{
+ int i;
+ char buf[50];
+
+ rewrite_rand_init();
+ sprintf(buf, "%.0f", (((double)rand()/RAND_MAX)*(h-l)));
+ i = atoi(buf)+1;
+ if (i < l) i = l;
+ if (i > h) i = h;
+ return i;
+}
+
+static char *select_random_value_part(request_rec *r, char *value)
+{
+ char *buf;
+ int n, i, k;
+
+ /* count number of distinct values */
+ for (n = 1, i = 0; value[i] != '\0'; i++)
+ if (value[i] == '|')
+ n++;
+
+ /* when only one value we have no option to choose */
+ if (n == 1)
+ return value;
+
+ /* else randomly select one */
+ k = rewrite_rand(1, n);
+
+ /* and grep it out */
+ for (n = 1, i = 0; value[i] != '\0'; i++) {
+ if (n == k)
+ break;
+ if (value[i] == '|')
+ n++;
+ }
+ buf = pstrdup(r->pool, &value[i]);
+ for (i = 0; buf[i] != '\0' && buf[i] != '|'; i++)
+ ;
+ buf[i] = '\0';
+ return buf;
+}
/*
@@ -2912,7 +3057,7 @@
continue;
}
}
- outp = ap_cpystrn(outp, cp, endp - outp);
+ outp = ap_cpystrn(outp, cp, endp - outp);
break;
}
return expanded ? pstrdup(r->pool, output) : str;
@@ -3010,7 +3155,7 @@
result = r->server->server_admin;
}
else if (strcasecmp(var, "SERVER_NAME") == 0) {
- result = get_server_name(r);
+ result = get_server_name(r);
}
else if (strcasecmp(var, "SERVER_PORT") == 0) {
ap_snprintf(resultbuf, sizeof(resultbuf), "%u", get_server_port(r));
Index: src/modules/standard/mod_rewrite.h
===================================================================
RCS file: /e/apache/REPOS/apache-1.3/src/modules/standard/mod_rewrite.h,v
retrieving revision 1.36
diff -u -r1.36 mod_rewrite.h
--- mod_rewrite.h 1998/01/07 16:46:56 1.36
+++ mod_rewrite.h 1998/02/12 14:27:23
@@ -184,6 +184,8 @@
#define MAPTYPE_TXT 1<<0
#define MAPTYPE_DBM 1<<1
#define MAPTYPE_PRG 1<<2
+#define MAPTYPE_INT 1<<3
+#define MAPTYPE_RND 1<<4
#define ENGINE_DISABLED 1<<0
#define ENGINE_ENABLED 1<<1
@@ -228,8 +230,10 @@
char *datafile; /* filename for map data files */
char *checkfile; /* filename to check for map existence */
int type; /* the type of the map */
- int fpin; /* in filepointer for program maps */
- int fpout; /* out filepointer for program maps */
+ int fpin; /* in file pointer for program maps */
+ int fpout; /* out file pointer for program maps */
+ char *(*func)(request_rec *, /* function pointer for internal maps */
+ char *);
} rewritemap_entry;
typedef struct {
@@ -385,13 +389,19 @@
static char *expand_tildepaths(request_rec *r, char *uri);
static void expand_map_lookups(request_rec *r, char *uri, int uri_len);
- /* DBM hashfile support functions */
+ /* rewrite map support functions */
static char *lookup_map(request_rec *r, char *name, char *key);
static char *lookup_map_txtfile(request_rec *r, char *file, char *key);
#if HAS_NDBM_LIB
static char *lookup_map_dbmfile(request_rec *r, char *file, char *key);
#endif
static char *lookup_map_program(request_rec *r, int fpin, int fpout, char *key);
+static char *lookup_map_internal(request_rec *r, char *(*func)(request_rec *r, char *key), char *key);
+static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
+static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
+static char *select_random_value_part(request_rec *r, char *value);
+static void rewrite_rand_init(void);
+static int rewrite_rand(int l, int h);
/* rewriting logfile support */
static void open_rewritelog(server_rec *s, pool *p);