[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[Libevent-users] Introducing libevscgi, a new libevent-based SCGI server



(Sorry if this is a double-post; I mistakenly sent it to the old monkey.org address the first time.)

Recently I've been porting the evhttp server from libevent to the SCGI (Simple Common Gateway Interface) protocol. I got it to respond to test requests correctly for the first time yesterday, so I've uploaded it to Gitorious: https://gitorious.org/libevscgi

The API is mostly the same as evhttp. The biggest difference is that it only implements the server side of the protocol. Another difference is that it only supports Unix domain sockets (though I'll probably add support for TCP sockets later). Also, it uses a few parts of evhttp itself, such as the URI-manipulation functions, the functions for manipulating the TAILQ header-lists, and the response-code symbolic names.

Here is a simple example, taken from the evhttp example https://gist.github.com/793194 with a few minor changes, that demonstrates how to handle SCGI requests in your program:

   #include <event.h>
   #include <event2/http.h> /* Currently only used for response status code constants. */
   #include <evscgi/evscgi.h>

   void process_request(struct evscgi_request *req, void *arg)
   {
     struct evbuffer *buf = evbuffer_new();
     if (buf == NULL) return;
     evbuffer_add_printf(buf, "Hello world.\n");
     evscgi_send_reply(req, HTTP_OK, "OK", buf);
     evbuffer_free(buf);
   }

   int main(int argc, char **argv)
   {
     struct event_base *base = NULL;
     struct evscgi *scgi = NULL;
     base = event_base_new();
     if (base == NULL) return -1;
     scgi = evscgi_new(base);
     if (scgi == NULL) return -1;
     if (evscgi_bind_unix_socket(scgi, "./scgi_socket") != 0) return -1;
     evscgi_set_gencb(scgi, process_request, NULL);
     event_base_dispatch(base);
   }

I don't necessarily mean to keep the API as close as possible to evhttp, however. In particular, I'm thinking of making it possible for an application to receive a request body as a series of chunks (to avoid keeping the whole thing in memory at once), or similarly to receive the headers in a one-at-a-time manner. I didn't know about libevhtp when I started this project, but I might change libevscgi's API to be more like it.

Also, it seems like it would be good to have a protocol-independent API for web applications, similar to Python's WSGI, but using a purely event-driven design. [1] This could be made as a pair of interface classes, one of which represents a request handler (with a method that's called once for each request, and/or several methods for receiving the request a piece at a time) and is implemented by the application, and the other of which represents a server (with methods for registering the application's request handlers with the server instance) and is implemented by wrapper libraries for the different server backends (such as libevhtp, evhttp, libevscgi, and possibly others). (Maybe there should also be another pair of interface classes, one of which represents an active connection and is implemented by the library, the other of which represents an in-progress request and is implemented by the application.) I'm thinking of developing an API like this using either C++ or Vala.


[1] WSGI is not really designed for use in a single-threaded event-driven environment. It provides the request body to the handler as an "input stream" object which the handler blocking-reads from; also, the handler itself provides the response body to the middleware either by returning all of it at once or else "yield"-ing it a piece at a time, in response to one or more pull-requests from the middleware. This design basically forces the middleware to have one process/thread per request, or else handle the requests in a purely serial manner.
***********************************************************************
To unsubscribe, send an e-mail to majordomo@xxxxxxxxxxxxx with
unsubscribe libevent-users    in the body.