changeset 863:305bc0a431de

.msgs processing in FastCGI
author Adam Chlipala <adamc@hcoop.net>
date Sat, 27 Jun 2009 17:50:31 -0400
parents 66dbf3953758
children 6304f5e8fbb4
files demo/prose include/request.h include/urweb.h src/c/cgi.c src/c/fastcgi.c src/c/http.c src/c/request.c src/c/urweb.c src/cjr_print.sml src/demo.sml
diffstat 10 files changed, 99 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/demo/prose	Sat Jun 27 16:56:32 2009 -0400
+++ b/demo/prose	Sat Jun 27 17:50:31 2009 -0400
@@ -19,8 +19,8 @@
 
 <blockquote><pre>Alias /demo/ "DIR/demo/out/"
 
-ProxyPass /Demo/ http://localhost:8080/
-ProxyPassReverse /Demo/ http://localhost:8080/</pre></blockquote></p>
+ProxyPass /Demo/ http://localhost:8080/Demo/
+ProxyPassReverse /Demo/ http://localhost:8080/Demo/</pre></blockquote></p>
 
 <p>Building the demo also generates a <tt>demo.sql</tt> file, giving the SQL commands to run to define all of the tables and sequences that the applications expect to see.  The file <tt>demo.urp</tt> contains a <tt>database</tt> line with the PostgreSQL database that the demo web server will try to connect to.</p>
 
--- a/include/request.h	Sat Jun 27 16:56:32 2009 -0400
+++ b/include/request.h	Sat Jun 27 17:50:31 2009 -0400
@@ -18,7 +18,9 @@
                           char *body, size_t body_len,
                           void (*on_success)(uw_context), void (*on_failure)(uw_context),
                           void *logger_data, uw_logger log_error, uw_logger log_debug,
-                          int sock);
+                          int sock,
+                          int (*send)(int sockfd, const void *buf, ssize_t len),
+                          int (*close)(int fd));
 
 uw_context uw_request_new_context(void *logger_data, uw_logger log_error, uw_logger log_debug);
 
--- a/include/urweb.h	Sat Jun 27 16:56:32 2009 -0400
+++ b/include/urweb.h	Sat Jun 27 17:50:31 2009 -0400
@@ -5,13 +5,15 @@
 
 #include "types.h"
 
-int uw_really_send(int sock, void *buf, ssize_t len);
+int uw_really_send(int sock, const void *buf, ssize_t len);
 
 extern uw_unit uw_unit_v;
 
 void uw_global_init(void);
 
-void uw_client_connect(unsigned id, int pass, int sock);
+void uw_client_connect(unsigned id, int pass, int sock,
+                       int (*send)(int sockfd, const void *buf, size_t len),
+                       int (*close)(int fd));
 void uw_prune_clients(uw_context);
 failure_kind uw_initialize(uw_context);
 
@@ -43,7 +45,7 @@
 
 int uw_send(uw_context, int sock);
 int uw_print(uw_context, int fd);
-int uw_output(uw_context ctx, int (*output)(void *data, char *buf, size_t len), void *data);
+int uw_output(uw_context ctx, int (*output)(void *data, const char *buf, size_t len), void *data);
 
 int uw_set_input(uw_context, const char *name, char *value);
 int uw_set_file_input(uw_context, char *name, uw_Basis_file);
--- a/src/c/cgi.c	Sat Jun 27 16:56:32 2009 -0400
+++ b/src/c/cgi.c	Sat Jun 27 17:50:31 2009 -0400
@@ -103,7 +103,7 @@
   rr = uw_request(rc, ctx, method, path, query_string, body, body_pos,
                   on_success, on_failure,
                   NULL, log_error, log_debug,
-                  -1);
+                  -1, NULL, NULL);
   uw_print(ctx, 1);
 
   if (rr == SERVED)
--- a/src/c/fastcgi.c	Sat Jun 27 16:56:32 2009 -0400
+++ b/src/c/fastcgi.c	Sat Jun 27 17:50:31 2009 -0400
@@ -113,7 +113,7 @@
   uw_write_header(ctx, "Status: 500 Internal Server Error\r\n");
 }
 
-static int write_stdout(void *data, char *buf, size_t len) {
+static int write_stdout(void *data, const char *buf, size_t len) {
   FCGI_Output *o = (FCGI_Output *)data;
   while (len > 0) {
     size_t len2 = len;
@@ -256,6 +256,42 @@
   return 0;
 }
 
+static int fastcgi_close_with(FCGI_Output *out, request_result rr) {
+  FCGI_EndRequestBody *erb = (FCGI_EndRequestBody *)out->r.contentData;
+
+  close_stream(out, FCGI_STDOUT);
+  close_stream(out, FCGI_STDERR);
+
+  if (rr == SERVED)
+    erb->appStatusB3 = erb->appStatusB2 = erb->appStatusB1 = erb->appStatusB0 = 0;
+  else
+    erb->appStatusB3 = erb->appStatusB2 = erb->appStatusB1 = erb->appStatusB0 = 0xFF;
+
+  erb->protocolStatus = FCGI_REQUEST_COMPLETE;
+  fastcgi_send(out, FCGI_END_REQUEST, sizeof(FCGI_EndRequestBody));
+  return close(out->sock);
+}
+
+static int fastcgi_close(int sock) {
+  FCGI_Output out;
+  out.sock = sock;
+  out.r.version = FCGI_VERSION_1;
+  out.r.paddingLength = 0;
+  out.r.reserved = 0;
+
+  return fastcgi_close_with(&out, SERVED);
+}
+
+int fastcgi_send_normal(int sock, const void *buf, ssize_t len) {
+  FCGI_Output out;
+  out.sock = sock;
+  out.r.version = FCGI_VERSION_1;
+  out.r.paddingLength = 0;
+  out.r.reserved = 0;
+
+  return write_stdout(&out, buf, len);
+}
+
 static void *worker(void *data) {
   int me = *(int *)data;
   FCGI_Input *in = fastcgi_input();
@@ -411,27 +447,18 @@
 
     {
       request_result rr;
-      FCGI_EndRequestBody *erb = (FCGI_EndRequestBody *)out->r.contentData;
 
       rr = uw_request(rc, ctx, method, path, query_string, body, body_read,
                       on_success, on_failure,
                       out, log_error, log_debug,
-                      in->sock);
+                      in->sock, fastcgi_send_normal, fastcgi_close);
 
       if (rr == KEEP_OPEN)
         goto done2;
 
       uw_output(ctx, write_stdout, out);
-      close_stream(out, FCGI_STDOUT);
-      close_stream(out, FCGI_STDERR);
-
-      if (rr == SERVED)
-        erb->appStatusB3 = erb->appStatusB2 = erb->appStatusB1 = erb->appStatusB0 = 0;
-      else
-        erb->appStatusB3 = erb->appStatusB2 = erb->appStatusB1 = erb->appStatusB0 = 0xFF;
-
-      erb->protocolStatus = FCGI_REQUEST_COMPLETE;
-      fastcgi_send(out, FCGI_END_REQUEST, sizeof(FCGI_EndRequestBody));
+      fastcgi_close_with(out, rr);
+      goto done2;
     }
 
   done:
--- a/src/c/http.c	Sat Jun 27 16:56:32 2009 -0400
+++ b/src/c/http.c	Sat Jun 27 17:50:31 2009 -0400
@@ -188,7 +188,7 @@
         rr = uw_request(rc, ctx, method, path, query_string, body, back - body,
                         on_success, on_failure,
                         NULL, log_error, log_debug,
-                        sock);
+                        sock, uw_really_send, close);
         uw_send(ctx, sock);
 
         if (rr == SERVED || rr == FAILED)
--- a/src/c/request.c	Sat Jun 27 16:56:32 2009 -0400
+++ b/src/c/request.c	Sat Jun 27 17:50:31 2009 -0400
@@ -151,12 +151,16 @@
   free(r);
 }
 
+extern char *uw_url_prefix;
+
 request_result uw_request(uw_request_context rc, uw_context ctx,
                           char *method, char *path, char *query_string,
                           char *body, size_t body_len,
                           void (*on_success)(uw_context), void (*on_failure)(uw_context),
                           void *logger_data, uw_logger log_error, uw_logger log_debug,
-                          int sock) {
+                          int sock,
+                          int (*send)(int sockfd, const void *buf, size_t len),
+                          int (*close)(int fd)) {
   int retries_left = MAX_RETRIES;
   char *s;
   failure_kind fk;
@@ -201,7 +205,8 @@
     return FAILED;
   }
 
-  if (!strcmp(path, "/.msgs")) {
+  if (!strncmp(path, uw_url_prefix, strlen(uw_url_prefix))
+      && !strcmp(path + strlen(uw_url_prefix), ".msgs")) {
     char *id = uw_Basis_requestHeader(ctx, "UrWeb-Client");
     char *pass = uw_Basis_requestHeader(ctx, "UrWeb-Pass");
 
@@ -212,7 +217,7 @@
 
     if (id && pass) {
       unsigned idn = atoi(id);
-      uw_client_connect(idn, atoi(pass), sock);
+      uw_client_connect(idn, atoi(pass), sock, send, close);
       log_error(logger_data, "Processed request for messages by client %u\n\n", idn);
       return KEEP_OPEN;
     }
--- a/src/c/urweb.c	Sat Jun 27 16:56:32 2009 -0400
+++ b/src/c/urweb.c	Sat Jun 27 17:50:31 2009 -0400
@@ -19,7 +19,7 @@
 
 // Socket extras
 
-int uw_really_send(int sock, const void *buf, size_t len) {
+int uw_really_send(int sock, const void *buf, ssize_t len) {
   while (len > 0) {
     ssize_t n = send(sock, buf, len, 0);
 
@@ -112,6 +112,8 @@
   pthread_mutex_t lock, pull_lock;
   buf msgs;
   int sock;
+  int (*send)(int sockfd, const void *buf, ssize_t len);
+  int (*close)(int fd);
   time_t last_contact;
   unsigned n_channels;
   unsigned refcount;
@@ -202,7 +204,9 @@
   on_success = s;
 }
 
-void uw_client_connect(unsigned id, int pass, int sock) {
+void uw_client_connect(unsigned id, int pass, int sock,
+                       int (*send)(int sockfd, const void *buf, ssize_t len),
+                       int (*close)(int fd)) {
   client *c = find_client(id);
 
   if (c == NULL) {
@@ -228,21 +232,24 @@
   }
 
   if (c->sock != -1) {
-    close(c->sock);
+    c->close(c->sock);
     c->sock = -1;
   }
 
   c->last_contact = time(NULL);
 
   if (buf_used(&c->msgs) > 0) {
-    uw_really_send(sock, on_success, strlen(on_success));
-    uw_really_send(sock, begin_msgs, sizeof(begin_msgs) - 1);
-    uw_really_send(sock, c->msgs.start, buf_used(&c->msgs));
+    send(sock, on_success, strlen(on_success));
+    send(sock, begin_msgs, sizeof(begin_msgs) - 1);
+    send(sock, c->msgs.start, buf_used(&c->msgs));
     buf_reset(&c->msgs);
     close(sock);
   }
-  else
+  else {
     c->sock = sock;
+    c->send = send;
+    c->close = close;
+  }
 
   pthread_mutex_unlock(&c->lock);
 }
@@ -264,10 +271,10 @@
   pthread_mutex_lock(&c->lock);
 
   if (c->sock != -1) {
-    uw_really_send(c->sock, on_success, strlen(on_success));
-    uw_really_send(c->sock, begin_msgs, sizeof(begin_msgs) - 1);
-    uw_really_send(c->sock, msg->start, buf_used(msg));
-    close(c->sock);
+    c->send(c->sock, on_success, strlen(on_success));
+    c->send(c->sock, begin_msgs, sizeof(begin_msgs) - 1);
+    c->send(c->sock, msg->start, buf_used(msg));
+    c->close(c->sock);
     c->sock = -1;
   } else
     buf_append(&c->msgs, msg->start, buf_used(msg));
--- a/src/cjr_print.sml	Sat Jun 27 16:56:32 2009 -0400
+++ b/src/cjr_print.sml	Sat Jun 27 17:50:31 2009 -0400
@@ -2816,6 +2816,16 @@
                         Link => false
                       | Action ef => ef = ReadCookieWrite
                       | Rpc ef => ef = ReadCookieWrite
+
+                val s =
+                    case Settings.getUrlPrefix () of
+                        "" => s
+                      | "/" => s
+                      | prefix =>
+                        if size s > 0 andalso String.sub (s, 0) = #"/" then
+                            prefix ^ String.extract (s, 1, NONE)
+                        else
+                            prefix ^ s
             in
                 box [string "if (!strncmp(request, \"",
                      string (String.toString s),
@@ -3274,6 +3284,12 @@
              newline,
              newline,
 
+             string "const char *uw_url_prefix = \"",
+             string (Settings.getUrlPrefix ()),
+             string "\";",
+             newline,
+             newline,
+
              string "static const char begin_xhtml[] = \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" ?>\\n<!DOCTYPE html PUBLIC \\\"-//W3C//DTD XHTML 1.0 Transitional//EN\\\" \\\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\\\">\\n<html xmlns=\\\"http://www.w3.org/1999/xhtml\\\" xml:lang=\\\"en\\\" lang=\\\"en\\\">\";",
              newline,
              newline,
@@ -3324,7 +3340,10 @@
 
              string "void uw_handle(uw_context ctx, char *request) {",
              newline,
-             string "if (!strcmp(request, \"/app.js\")) {",
+             string "if (!strcmp(request, \"",
+             string (OS.Path.joinDirFile {dir = Settings.getUrlPrefix (),
+                                          file = "app.js"}),
+             string "\")) {",
              newline,
              box [string "uw_write_header(ctx, \"Content-type: text/javascript\\r\\n\");",
                   newline,
--- a/src/demo.sml	Sat Jun 27 16:56:32 2009 -0400
+++ b/src/demo.sml	Sat Jun 27 17:50:31 2009 -0400
@@ -92,7 +92,7 @@
                                        file = "demo.exe"},
             sql = SOME (OS.Path.joinDirFile {dir = dirname,
                                              file = "demo.sql"}),
-            debug = false,
+            debug = Settings.getDebug (),
             timeout = Int.max (#timeout combined, #timeout urp),
             profile = false,
             ffi = [],