DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=8882>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=8882

[PATCH] mod_rewrite communicates with external rewrite engine over TCP/IP

           Summary: [PATCH] mod_rewrite communicates with external rewrite
                    engine over TCP/IP
           Product: Apache httpd-1.3
           Version: 1.3.24
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Enhancement
          Priority: Other
         Component: mod_rewrite
        AssignedTo: bugs@httpd.apache.org
        ReportedBy: [EMAIL PROTECTED]


The stock mod_rewrite interface with an external rewrite engine via stdin/stdout
requires a lockfile to prevent multiple child processes screwing up each other's
rewriting.  This essentially means that all rewrite processes are serialised,
and can result in a serious queuing of requests if the rewrite program
encounters any delay.

The following patch will enable mod_rewrite to communicate with the external
rewrite engine over TCP/IP sockets, meaning that a multi-threaded (or
multi-process, you choose) rewrite engine can deal with several rewrite requests
at once, without the need to serialise the requests.  I'm not suggesting for one
minute that it's perfect, or even close, but it's a means to an end and it
actually works.

There's a slight change to the RewriteMap directive:

RewriteMap name "prg:/path/to/prog args" port

Where port is the port to send rewrite requests to.  I'm sure this could be done
more elegantly by having an extra RewriteMap type, but tying it into the prg:
type does have the advantage of ensuring that the process is up and running at
the same time Apache is.

--- src/modules/standard/mod_rewrite.c  Tue May  7 16:34:43 2002
+++ /home/jtait/src/apache_1.3.24/src/modules/standard/mod_rewrite.c    Tue May
 7 16:14:34 2002
@@ -168,7 +168,7 @@
       "an input string and a to be applied regexp-pattern" },
     { "RewriteRule",     cmd_rewriterule,     NULL, OR_FILEINFO, RAW_ARGS,
       "an URL-applied regexp-pattern and a substitution URL" },
-    { "RewriteMap",      cmd_rewritemap,      NULL, RSRC_CONF,   TAKE2,
+    { "RewriteMap",      cmd_rewritemap,      NULL, RSRC_CONF,   TAKE23,
       "a mapname and a filename" },
     { "RewriteLock",     cmd_rewritelock,     NULL, RSRC_CONF,   TAKE1,
       "the filename of a lockfile used for inter-process synchronization"},
@@ -448,7 +448,7 @@
 }

 static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1,
-                                  char *a2)
+                                  char *a2, char *a3)
 {
     rewrite_server_conf *sconf;
     rewritemap_entry *new;
@@ -485,6 +485,12 @@
         new->type = MAPTYPE_PRG;
         new->datafile = a2+4;
         new->checkfile = a2+4;
+        if (a3 == NULL) {
+            new->port = 0;
+        }
+       else {
+            new->port = atoi(a3);
+        }
     }
     else if (strncmp(a2, "int:", 4) == 0) {
         new->type      = MAPTYPE_INT;
@@ -2753,7 +2759,7 @@
             }
             else if (s->type == MAPTYPE_PRG) {
                 if ((value =
-                     lookup_map_program(r, s->fpin, s->fpout, key)) != NULL) {
+                     lookup_map_program(r, s->fpin, s->fpout, key, s->port)) !=
NULL) {
                     rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
                                s->name, key, value);
                     return value;
@@ -2891,11 +2897,12 @@
 }
 #endif

-static char *lookup_map_program(request_rec *r, int fpin, int fpout, char *key)
+static char *lookup_map_program(request_rec *r, int fpin, int fpout, char *key,
unsigned short port)
 {
     char buf[LONG_STRING_LEN];
     char c;
     int i;
+    int sock;
 #ifndef NO_WRITEV
     struct iovec iov[2];
 #endif
@@ -2909,33 +2916,71 @@
         return NULL;
     }

-    /* take the lock */
-    rewritelock_alloc(r);
+    if (port != 0) {
+        /* create a socket connection to the external program */
+        sock = make_socket_connection(r, port);
+        if (sock == -1) {
+            return NULL;
+        }
+
+        ap_hard_timeout("Send external rewrite request", r);
+        /* write out the request key */
+        i = send(sock, key, strlen(key), 0);
+        if (i != strlen(key)) {
+            ap_kill_timeout(r);
+            return NULL;
+        }
+        ap_reset_timeout(r);
+
+        i = send(sock, "\n", 1, 0);
+        if (i != 1) {
+            ap_kill_timeout(r);
+            return NULL;
+        }
+        ap_kill_timeout(r);
+
+        /* read in the response value */
+        ap_hard_timeout("Receive external rewrite response", r);
+        i = 0;
+        while (recv(sock, &c, 1, 0) == 1 && (i < LONG_STRING_LEN -1)) {
+            if (c == '\n') {
+                break;
+            }
+            buf[i++] = c;
+        }
+        buf[i] = '\0';
+        ap_pclosesocket(r->pool, sock);
+        ap_kill_timeout(r);
+    }
+    else {
+        /* take the lock */
+        rewritelock_alloc(r);

-    /* write out the request key */
+        /* write out the request key */
 #ifdef NO_WRITEV
-    write(fpin, key, strlen(key));
-    write(fpin, "\n", 1);
+        write(fpin, key, strlen(key));
+        write(fpin, "\n", 1);
 #else
-    iov[0].iov_base = key;
-    iov[0].iov_len = strlen(key);
-    iov[1].iov_base = "\n";
-    iov[1].iov_len = 1;
-    writev(fpin, iov, 2);
+        iov[0].iov_base = key;
+        iov[0].iov_len = strlen(key);
+        iov[1].iov_base = "\n";
+        iov[1].iov_len = 1;
+        writev(fpin, iov, 2);
 #endif

-    /* read in the response value */
-    i = 0;
-    while (read(fpout, &c, 1) == 1 && (i < LONG_STRING_LEN-1)) {
-        if (c == '\n') {
-            break;
+        /* read in the response value */
+        i=0;
+        while (read(fpout, &c, 1) == 1 && (i < LONG_STRING_LEN-1)) {
+            if (c == '\n') {
+                break;
+            }
+            buf[i++] = c;
         }
-        buf[i++] = c;
-    }
-    buf[i] = '\0';
+        buf[i] = '\0';

-    /* give the lock back */
-    rewritelock_free(r);
+        /* give the lock back */
+        rewritelock_free(r);
+    }

     if (strcasecmp(buf, "NULL") == 0) {
         return NULL;
@@ -2945,6 +2990,45 @@
     }
 }

+static int make_socket_connection(request_rec *r, unsigned short port)
+{
+    struct hostent *server_hp;
+    struct sockaddr_in addr;
+    int sock;
+    int i;
+
+    memset(&addr, '\0', sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port   = htons(port);
+
+    server_hp = gethostbyname("localhost");
+    addr.sin_addr.s_addr =  ((struct in_addr 
*)server_hp->h_addr_list[0])->s_addr;
+
+    sock = ap_psocket(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (sock == -1) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "Unable to create socket");
+        return -1;
+    }
+
+    ap_hard_timeout("External rewriter connect", r);
+    do {
+        i = connect(sock, (struct sockaddr *) &addr, sizeof(struct 
sockaddr_in));
+#if defined(WIN32) || defined(NETWARE)
+        if (i == SOCKET_ERROR) {
+            errno = WSAGetLastError();
+        }
+#endif /* WIN32 */
+    } while (i == -1 && errno == EINTR);
+    if (i == -1) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
+                      "Unable to connect to external rewriter on %s:%d",
+                      inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+        sock = -1;
+    }
+    ap_kill_timeout(r);
+    return sock;
+}
+
 static char *lookup_map_internal(request_rec *r,
                                  char *(*func)(request_rec *, char *),
                                  char *key)
--- src/modules/standard/mod_rewrite.h  Tue May  7 16:34:43 2002
+++ /home/jtait/src/apache_1.3.24/src/modules/standard/mod_rewrite.h    Fri May
 3 17:18:39 2002
@@ -274,6 +274,7 @@
     int   fperr;                   /* err file pointer for program maps */
     char *(*func)(request_rec *,   /* function pointer for internal maps */
                   char *);
+    unsigned short port;           /* port number for program maps */
 } rewritemap_entry;

 typedef struct {
@@ -383,7 +384,7 @@
 static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, char *a1);
 static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
 static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, char *a1,
-                                       char *a2);
+                                       char *a2, char *a3);
 static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1);
 static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
                                    char *a1);
@@ -440,7 +441,8 @@
 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);
+                                int fpout, char *key, unsigned short port);
+static int make_socket_connection(request_rec *r, unsigned short port);
 static char *lookup_map_internal(request_rec *r,
                                  char *(*func)(request_rec *r, char *key),
                                  char *key);

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to