summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2009-06-27 17:50:31 -0400
committerGravatar Adam Chlipala <adamc@hcoop.net>2009-06-27 17:50:31 -0400
commitb9fcbe3dc86323a4a64b419c589a1cc5eeb38749 (patch)
treefb74e59d4dc2a663499f25e692fac8f08e6cb266
parente549f22abb97951897b9eaebee879addd66f2517 (diff)
.msgs processing in FastCGI
-rw-r--r--demo/prose4
-rw-r--r--include/request.h4
-rw-r--r--include/urweb.h8
-rw-r--r--src/c/cgi.c2
-rw-r--r--src/c/fastcgi.c53
-rw-r--r--src/c/http.c2
-rw-r--r--src/c/request.c11
-rw-r--r--src/c/urweb.c29
-rw-r--r--src/cjr_print.sml21
-rw-r--r--src/demo.sml2
10 files changed, 99 insertions, 37 deletions
diff --git a/demo/prose b/demo/prose
index 0c443692..37b49a90 100644
--- a/demo/prose
+++ b/demo/prose
@@ -19,8 +19,8 @@ to build the "Hello World" demo application. Whether building the pieces separa
<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>
diff --git a/include/request.h b/include/request.h
index e319e91a..73ee0468 100644
--- a/include/request.h
+++ b/include/request.h
@@ -18,7 +18,9 @@ request_result uw_request(uw_request_context, uw_context,
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);
diff --git a/include/urweb.h b/include/urweb.h
index 6adc8969..7b247f62 100644
--- a/include/urweb.h
+++ b/include/urweb.h
@@ -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 @@ void uw_memstats(uw_context);
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);
diff --git a/src/c/cgi.c b/src/c/cgi.c
index 1d92073d..38cb7da4 100644
--- a/src/c/cgi.c
+++ b/src/c/cgi.c
@@ -103,7 +103,7 @@ int main(int argc, char *argv[]) {
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)
diff --git a/src/c/fastcgi.c b/src/c/fastcgi.c
index 369b6d96..ed51133a 100644
--- a/src/c/fastcgi.c
+++ b/src/c/fastcgi.c
@@ -113,7 +113,7 @@ static void on_failure(uw_context ctx) {
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 @@ static int read_nvp(char *buf, int len, nvp *nv) {
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 @@ static void *worker(void *data) {
{
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:
diff --git a/src/c/http.c b/src/c/http.c
index e4e79848..9550bd4f 100644
--- a/src/c/http.c
+++ b/src/c/http.c
@@ -188,7 +188,7 @@ static void *worker(void *data) {
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)
diff --git a/src/c/request.c b/src/c/request.c
index 0dbf6290..bbc39d34 100644
--- a/src/c/request.c
+++ b/src/c/request.c
@@ -151,12 +151,16 @@ void uw_free_request_context(uw_request_context r) {
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 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
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 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
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;
}
diff --git a/src/c/urweb.c b/src/c/urweb.c
index f5f11a2b..6e217e08 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -19,7 +19,7 @@ uw_unit uw_unit_v = {};
// 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 @@ typedef struct client {
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 @@ void uw_set_on_success(char *s) {
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 @@ void uw_client_connect(unsigned id, int pass, int sock) {
}
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 @@ static void client_send(client *c, buf *msg) {
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));
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index b8db23e8..14721edd 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -2816,6 +2816,16 @@ fun p_file env (ds, ps) =
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 @@ fun p_file env (ds, ps) =
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 @@ fun p_file env (ds, ps) =
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,
diff --git a/src/demo.sml b/src/demo.sml
index a2312d98..21242d73 100644
--- a/src/demo.sml
+++ b/src/demo.sml
@@ -92,7 +92,7 @@ fun make {prefix, dirname, guided} =
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 = [],