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]