diff options
author | Adam Chlipala <adamc@hcoop.net> | 2009-06-27 17:50:31 -0400 |
---|---|---|
committer | Adam Chlipala <adamc@hcoop.net> | 2009-06-27 17:50:31 -0400 |
commit | b9fcbe3dc86323a4a64b419c589a1cc5eeb38749 (patch) | |
tree | fb74e59d4dc2a663499f25e692fac8f08e6cb266 | |
parent | e549f22abb97951897b9eaebee879addd66f2517 (diff) |
.msgs processing in FastCGI
-rw-r--r-- | demo/prose | 4 | ||||
-rw-r--r-- | include/request.h | 4 | ||||
-rw-r--r-- | include/urweb.h | 8 | ||||
-rw-r--r-- | src/c/cgi.c | 2 | ||||
-rw-r--r-- | src/c/fastcgi.c | 53 | ||||
-rw-r--r-- | src/c/http.c | 2 | ||||
-rw-r--r-- | src/c/request.c | 11 | ||||
-rw-r--r-- | src/c/urweb.c | 29 | ||||
-rw-r--r-- | src/cjr_print.sml | 21 | ||||
-rw-r--r-- | src/demo.sml | 2 |
10 files changed, 99 insertions, 37 deletions
@@ -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 = [], |