Mercurial > urweb
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 = [],