extern(C) { enum { MONGREL_CONTENT_LENGTH , MONGREL_CONTENT_TYPE , MONGREL_FRAGMENT , MONGREL_HTTP_VERSION , MONGREL_QUERY_STRING , MONGREL_REQUEST_PATH , MONGREL_REQUEST_METHOD , MONGREL_REQUEST_URI }; typedef void (*field_cb)(void *data, char *field, size_t flen, char *value, size_t vlen); typedef void (*element_cb)(void *data, int type, char *at, size_t length); struct http_parser { int cs; int overflow_error; size_t body_start; size_t content_length; size_t nread; size_t mark; size_t field_start; size_t field_len; size_t query_start; void *data; field_cb http_field; element_cb on_element; }; void http_parser_init(http_parser *parser); int http_parser_finish(http_parser *parser); size_t http_parser_execute(http_parser *parser, char *data, size_t len, size_t off); int http_parser_has_error(http_parser *parser); int http_parser_is_finished(http_parser *parser); }
extern (C) void http_field_cb(void *data, char *field, size_t flen, char *value, size_t vlen) { ...code here... } extern (C) void on_element(void *data, int type, char *at, size_t length) { ...code here... }
import tango.io.Stdout; import tango.stdc.stringz; import tango.net.ServerSocket, tango.net.SocketConduit; // Stuff for the mongrel parser extern(C) { enum { MONGREL_CONTENT_LENGTH , MONGREL_CONTENT_TYPE , MONGREL_FRAGMENT , MONGREL_HTTP_VERSION , MONGREL_QUERY_STRING , MONGREL_REQUEST_PATH , MONGREL_REQUEST_METHOD , MONGREL_REQUEST_URI }; typedef void (*field_cb)(void *data, char *field, size_t flen, char *value, size_t vlen); typedef void (*element_cb)(void *data, int type, char *at, size_t length); struct http_parser { int cs; int overflow_error; size_t body_start; size_t content_length; size_t nread; size_t mark; size_t field_start; size_t field_len; size_t query_start; void *data; field_cb http_field; element_cb on_element; }; void http_parser_init(http_parser *parser); int http_parser_finish(http_parser *parser); size_t http_parser_execute(http_parser *parser, char *data, size_t len, size_t off); int http_parser_has_error(http_parser *parser); int http_parser_is_finished(http_parser *parser); } // End of stuff for the mongrel parser // My callback functions extern (C) void http_field_cb(void *data, char *field, size_t flen, char *value, size_t vlen) { char[]* display = cast(char[]*)data; *display ~= "<i>http_field_cb</i> <b>"; *display ~= field[0..flen]; *display ~= "</b> = "; *display ~= value[0..vlen]; *display ~= "<br>"; } extern (C) void on_element(void *data, int type, char *at, size_t length) { char[]* display = cast(char[]*)data; char[] line; line ~= "<i>on_element</i> <b>"; if (type==MONGREL_CONTENT_LENGTH) line ~= "MONGREL_CONTENT_LENGTH"; if (type==MONGREL_CONTENT_TYPE) line ~= "MONGREL_CONTENT_TYPE"; if (type==MONGREL_FRAGMENT) line ~= "MONGREL_FRAGMENT"; if (type==MONGREL_HTTP_VERSION) line ~= "MONGREL_HTTP_VERSION"; if (type==MONGREL_QUERY_STRING) line ~= "MONGREL_QUERY_STRING"; if (type==MONGREL_REQUEST_PATH) line ~= "MONGREL_REQUEST_PATH"; if (type==MONGREL_REQUEST_METHOD) line ~= "MONGREL_REQUEST_METHOD"; if (type==MONGREL_REQUEST_URI) line ~= "MONGREL_REQUEST_URI"; line ~= "</b> = " ~ at[0..length] ~ "<br>"; *display ~= line; } void main() { // Set up the server Stdout("Now open your browser to http://localhost/").newline(); Stdout("Ctrl-Break or Ctrl-C to quit").newline(); auto server = new ServerSocket (new InternetAddress(80)); while(1) { // wait for requests SocketConduit request = server.accept; // wait for the 'http get ...' char[1024] response; uint len = request.read (response); Stdout(response[0..len]).newline; // you'll want to comment this out if you run apachebench against this... // parse it char[] display; display = ""; http_parser parser; http_parser_init(&parser); parser.data = &display; // data that is sent to the callback function parser.http_field = &http_field_cb; parser.on_element = &on_element; http_parser_execute( &parser , cast(char*)response , len , 0 ); display ~= http_parser_has_error(&parser) ? "-mongrel error;" : "-no mongrel error;"; display ~= http_parser_is_finished(&parser) ? "mongrel finished-" : "mongrel not finished-";; // send HTML request.output.write("HTTP/1.1 200 OK <html> <style> body {font-family:trebuchet ms;background:#524D4A;color:#fff;} .comment {font-size:80%;margin:0;color:#cccccc;} form {background:#6B7552; margin:20px 0 20px 0; padding:5px;} </style> <body> <h1>D + Mongrel's HTTP parser</h1> <form method='get'> <h2>GET form</h2> <input name='blah' value='test value'> <input type='submit'> </form> <form method='post'> <h2>POST form</h2> <input name='blah' value='test value'> <input type='submit'> </form> <form method='post'> <h2>POST form with file</h2> <input type='file' name='blah'> <input type='submit'> </form> <form> <h2>Mongrel Parser Results:</h2> " ~ display ~ " </form> </body> </html>"); request.close(); } }
Thanks for reading! And if you want to get in touch, I'd love to hear from you: chris.hulbert at gmail.
(Comp Sci, Hons - UTS)
Software Developer (Freelancer / Contractor) in Australia.
I have worked at places such as Google, Cochlear, Assembly Payments, News Corp, Fox Sports, NineMSN, FetchTV, Coles, Woolworths, Trust Bank, and Westpac, among others. If you're looking for help developing an iOS app, drop me a line!
Get in touch:
[email protected]
github.com/chrishulbert
linkedin