Emacs Web Server User Manual
****************************

This file documents the Emacs Web Server (ews)

Copyright (C) 2013 Eric Schulte <schulte.eric@gmail.com>

     Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with the Invariant Section being ``GNU GENERAL PUBLIC LICENSE,'' A copy of the license is included in the section entitled ``GNU Free Documentation License.''

Introduction
************

The Emacs Web Server is a Web server implemented entirely in Emacs Lisp.  HTTP requests are matched to handlers (see Handlers) which are Emacs Lisp functions.  Handlers receive as their only argument a request object (see Requests) which holds information about the request and the process holding HTTP network connection.  Handlers write their responses directly to the network process.

A number of examples (see Usage Examples) demonstrate usage of the Emacs Web Server.  All public functions of the Emacs Web Server are listed (see Function Index).

Handlers
********

The function ews-start takes takes two arguments handlers and port.  It starts a server listening on port responding to requests with handlers, an association list composed of pairs of matchers and handler functions.

Matchers
========

Matchers may be a regular expression or a function.  Regular expression matchers consists of an HTTP header and a regular expression.  When the regular expression matches the content of the given header the matcher succeeds and the associated handler is called.  For example the following matches any GET request whose path starts with the substring ``foo''.

     (:GET . "^foo")

A function matcher is a function which takes the request object (see Requests) and succeeds when the function returns a non-nil value.  For example the following matcher matches every request,

     (lambda (_) t)

and the following matches only requests in which the supplied ``number'' parameter is odd.

     (lambda (request)
       (oddp (string-to-number (cdr (assoc "number" request)))))

Handler Function
================

Each handler is a function which takes a request object (see Requests) as its only argument.  The function may respond to the request by writing to the network process held in the process field of the request object.  For example, the process-send-string function may be used to write string data to a request as in the following.

       (process-send-string (process request) "hello world")

When the handler function exits the connection is terminated unless the handler function returns the keyword :keep-alive.

Requests
********

Each HTTP requests is represented using an ews-request object (see ews-request).  The request object is used to decide which handler to call, and is passed as an argument to the called handler. The request object holds the network process, all HTTP headers, and any parameters.

The text of the request is parsed into an alist.  HTML Headers are keyed using uppercase keywords (e.g., :GET), and user supplied parameters are keyed using the string name of the parameter.

Usage Examples
**************

These examples demonstrate usage.

Hello World
===========

The simplest possible ``hello world'' example.  The handler consists of a single (matcher . handler) pair.  The function matcher matches every incoming HTTP request.  The handler responds by setting the content type to text/plain, and then sending the string ``hello world''.  When the handler exits the network connection of the request is closed.

     [file 0-hello-world.el not included]

Hello World UTF8
================

This example only differs from the previous in that the ``Content-type'' indicates UTF8 encoded data, and the hello world sent is selected at random from a list of different languages.

     [file 1-hello-world-utf8.el not included]

Hello World HTML
================

     [file 2-hello-world-html.el not included]

This variation of the ``hello world'' example sends a text/html response instead of a simple text/plain response.

File Server
===========

The following example implements a file server which will serve files from the docroot document root set to the current working directory in this example.  Three helper functions are used; ews-subdirectoryp is used to check if the requested path is within the document root, if so the file is served and ews-send-file is used to appropriately set the mime-type of the response based on the extension of the file, if not then ews-send-404 is used to send a default ``File Not Found'' response.

     [file 3-file-server.el not included]

URL Parameter Echo
==================

This example demonstrates access of URL-encoded parameters in a GET request.  For example the following URL http://localhost:9005/example?foo=bar&baz=qux will render as an the following HTML table.

foo   bar
baz   qux

     [file 4-url-param-echo.el not included]

POST Echo
=========

The following example echos back the content of the ``message'' field in a POST request.

     [file 5-post-echo.el not included]

Function Index
**************

The following functions implement the Emacs Web Server public API.

Objects
=======

The following objects represent web servers and requests.

 -- Class: ews-server handlers process port requests
     Every Emacs web server is an instance of the ews-server class. Each instance includes the handlers association list and port passed to ews-start, as well as the server network process and a list of all active requests.

 -- Class: ews-request process pending context boundary headers
     The ews-request class represents an active web request.  The process field holds the network process of the client machine and may be used by handlers to respond to requests.  The headers field holds an alist of information on the request for use by handlers.  The remaining pending, context and boundary fields are used to maintain header parsing information across calls to the ews-filter function.

Starting and Stopping Servers
=============================

The following functions start and stop Emacs web servers.  The ews-servers list holds all running servers.

 -- Function: ews-start handlers port &optional log-buffer &rest network-args
     ews-start starts a server listening on port using handlers (see Handlers) to match and respond to requests. An instance of the ews-server class is returned.

 -- Variable: ews-servers
     The ews-servers list holds all active Emacs web servers.

 -- Function: ews-stop server
     ews-stop stops server deletes all related processes, and frees the server's port.  Evaluate the following to stop all emacs web servers.

          (mapc #'ews-stop ews-servers)

Convenience Functions
=====================

The following convenience functions automate many common tasks associated with responding to HTTP requests.

 -- Function: ews-response-header process code &rest header
     Send the headers required to start an HTTP response to process. process should be a ews-request process of an active request.  For example start a standard 200 ``OK'' HTML response with the following.

          (ews-response-header process 200 '("Content-type" . "text/html"))

     The encoding may optionally be set in the HTTP header.  Send a UTF8 encoded response with the following.

          (ews-response-header process 200
                      '("Content-type" . "text/plain; charset=utf-8"))

 -- Function: ews-send-500 process &rest msg-and-args
     ews-send-500 sends a default 500 ``Internal Server Error'' response to process.

 -- Function: ews-send-404 process &rest msg-and-args
     ews-send-500 sends a default 404 ``File Not Found'' response to process.

 -- Function: ews-send-file process path &optional mime-type
     ews-send-file sends the file located at path to process.  If the optional mime-type is not set, then the mime-type is determined by calling mm-default-file-encoding on path or is set to ``application/octet-stream'' if no mime-type can be determined.

 -- Function: ews-in-directory-p parent path
     Check if path is under the parent directory.

          (ews-in-directory-p "/tmp/" "pics")
              => "/tmp/pics"

          (ews-in-directory-p "/tmp/" "..")
              => nil

          (ews-in-directory-p "/tmp/" "~/pics")
              => nil

GNU GENERAL PUBLIC LICENSE
**************************

     [file gpl.texi not included]

GNU Free Documentation License
******************************

     [file doclicense.texi not included]