mongrel2

  1. mongrel2
    1. Description
    2. Author
    3. Caveat
    4. Documentation
      1. mongrel2-lolevel
      2. mongrel2
    5. Examples
      1. mongrel2-lolevel
      2. mongrel2

Description

This egg provides an API for writing Mongrel2 handlers. Mongrel2 strives to be an application, language, and network architecture agnostic web server. The server itself is written in C and is required to actually put handlers created with this egg to use. Mongrel2 communicates with its handlers via ZeroMQ.

The API comes in two flavors: mongrel2-lolevel which is modeled after the Python example handler code of the distribution (see examples/python in the Mongrel2 tarball) and mongrel2 which is built on top of that and modeled after spiffy's API.

Author

Moritz Heidkamp

Caveat

This API is very experimental and may change significantly in the near future.

Documentation

The following assumes that you are familiar with ZeroMQ as well as Mongrel2's architecture. If you aren't yet, go read the ZeroMQ guide and/or the Mongrel2 Manual.

mongrel2-lolevel

[procedure] (connect-handler id response-endpoint request-endpoint #!optional request-id)

Creates and connects two zmq sockets for communicating with a Mongrel2 server. The id is used as the PUB socket's identity and request-endpoint is a zmq endpoint string for that socket to connect to. Correspondingly, request-endpoint is the zmq endpoint string for the PULL socket to connect to. Optionally, an identity for that socket can be given as request-id. The return value is an opaque connection record which is further referred to as a connection.

[procedure] (receive-request connection)

Receives a request from connection. This will block the current thread until a request is available. Requests are returned in the form of a record which can be inspected with several procedures also available in this module.

[procedure] (request-disconnect? request)

Checks whether the given request signifies a disconnect event.

[procedure] (request-sender request)

Returns the given request's sender UUID as a string.

[procedure] (request-path request)

Returns the given request's URI path as a string.

[procedure] (request-headers request)

Returns the given request's headers as an alist with the keys being symbols.

[procedure] (request-header name request)

Return the value of request's header name which must be a symbol. If there no header of that name is found, #f is returned.

[procedure] (request-method request)

Returns the given request's method as a symbol, e.g. JSON or GET.

[procedure] (request-body request)

Returns the given request's body as a string.

[procedure] (request-data request)

Returns the given request's body in a structured format. This depends on the request's method. Currently it will only handle requests of the type JSON and return the body's contents parsed by the json egg.

[procedure] (request-id request)

Returns the given request's listener id as a string.

[procedure] (request-type)

Returns the given request's type as a symbol. This is either json, xml or http.

[procedure] (request-uri)

Returns the given request's URI as a uri-common record.

[procedure] (send-response request response)

Sends a response string for the given request.

[procedure] (send-http-response request #!key code reason body headers response)

Sends an HTTP response for the given request. The arguments are exactly the same as those of spiffy's send-response with the addition of the keyword argument response which can be used to pass in an intarweb response record to be used as a basis (default is an empty response record).

mongrel2

[parameter] (handler-response-id [id])

The response socket's identity string.

[parameter] (handler-response-endpoint [endpoint])

The response socket's endpoint string.

[parameter] (handler-request-id [id])

The request socket's identity string.

[parameter] (handler-request-endpoint [endpoint])

The request socket's endpoint string.

[parameter] (current-request [request])

The current Mongrel2 request record (see the mongrel2-lolevel module for available accessors).

[parameter] (current-http-request [http-request])

If the current-request's request-type is http, this parameter holds a corresponding intarweb request record. Otherwise it will be #f.

[parameter] (current-http-response [http-response])

If the current-request's request-type is http, this parameter holds an intarweb response record which can be used to build up a response. Otherwise it will be #f.

[procedure] (handler-start [handler])

Starts the handler mainloop. handler is a thunk which is called for each incoming request with the above paramters set accordingly. It is expected to send a response to current-request. See send-response and send-http-response on how to do that.

[procedure] (send-response body)

Sends the string body as the response for current-request.

[procedure] (send-http-response #!key code reason body headers)

Sends a HTTP response for current-request. This procedure works exactly like spiffy's send-response.

Examples

mongrel2-lolevel

(use mongrel2-lolevel)

(define conn (connect-handler "6cafb469-3b40-40c1-a50a-ede619ce3d16"
                              "tcp://127.0.0.1:1234"
                              "tcp://127.0.0.1:1235"
                              "55752929-b6c0-4015-9e9e-17c765c90a12"))

(let loop ()
  
  (print "WAITING FOR REQUEST")

  (let ((req (receive-request conn)))

    (if (request-disconnect? req)
        (print "DISCONNECT")
        (send-http-response req 
                            body: (format "\nSENDER: ~A\nIDENT: ~A\nPATH: ~A\nHEADERS: ~S\nBODY: ~A"
                                          (request-sender req)
                                          (request-id req)
                                          (request-path req)
                                          (request-headers req) 
                                          (request-body req))
                            headers: '((content-type text/plain)))))
  
  (loop))

mongrel2

(use mongrel2 uri-common (prefix intarweb http-))
                              
(handler-response-id "6cafb469-3b40-40c1-a50a-ede619ce3d16")
(handler-response-endpoint "tcp://127.0.0.1:1234")
(handler-request-id "55752929-b6c0-4015-9e9e-17c765c90a12")
(handler-request-endpoint "tcp://127.0.0.1:1235")

(handler-start (lambda ()
                 (let ((uri (uri->string (http-request-uri (current-http-request)))))
                   (send-http-response body: (format "thank you for requesting ~A" uri)))))