eschulte pushed a commit to branch master in repository elpa. commit 1b6b7f78d0a534bd3b322ec85d913be5bec6748e Author: Eric Schulte <schulte.e...@gmail.com> Date: Tue Dec 24 23:40:17 2013 -0700
more --- NOTES | 4 ++-- doc/emacs-web-server.texi | 42 ++++++++++++++++++++++++++++++++++++++++-- emacs-web-server-test.el | 3 --- emacs-web-server.el | 31 ++++++++++++++++++++++--------- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/NOTES b/NOTES index c8e10cb..476dd20 100644 --- a/NOTES +++ b/NOTES @@ -1,7 +1,7 @@ -*- org -*- * Notes -* Tasks [5/9] +* Tasks [6/9] ** TODO Documentation [0/4] - [ ] introduction - [ ] handlers @@ -23,7 +23,7 @@ For now keep this all incremental and in ews-filter. ** DONE catch errors and return an error code include an easy error handler like the 404 handler -** TODO better parsing of multipart form blocks +** DONE better parsing of multipart form blocks parse more than just the content-type headers. ** DONE non-multipart form data diff --git a/doc/emacs-web-server.texi b/doc/emacs-web-server.texi index 3d792c5..e41421e 100644 --- a/doc/emacs-web-server.texi +++ b/doc/emacs-web-server.texi @@ -65,7 +65,17 @@ Appendices @chapter Introduction @cindex introduction -This is the introduction. +The Emacs Web Server is a Web server implemented in Emacs Lisp using +Emacs network communication primitives. HTTP requests are matched to +handlers (@pxref{Handlers}) which are implemented as Emacs Lisp +functions. Handler functions receive the HTTP connection process and +a request object (@pxref{Request Headers}) which holds information +about the request. Handlers write responses directly to the +connection process. + +A number of examples (@pxref{Usage Examples}) demonstrate usage of the +Emacs Web Server, as well as a complete list of the functions defining +the interface (@pxref{Function Index}). @node Handlers, Request Headers, Handlers, Top @chapter Handlers @@ -77,7 +87,35 @@ A handler looks like this and does this. @chapter Request Headers @cindex request headers -Request headers have this information. +Information on requests is stored in a @code{request} object. This object is +used to decide which handler to call, and is passed to the called handler. +Request objects hold information such as the type of request (@code{GET}, +@code{POST}, etc.), the path of the request, and any parameter information +encoded in the request URL as form data. + +The request is received as a string which is parsed into an alist. +This parsing is only performed as needed by a handler or as necessary +to select a handler to call. HTML Headers are keyed using uppercase +keywords (e.g., @code{:GET}), and user supplied parameters are keyed +using the string name of the parameter. The following functions may +be used to read request alists and cause any needed parsing to take +place as a side effect. + +@defun ews-get item request +@code{ews-get} returns the value associated with @code{item} in +@code{request}. Any pending parsing of the @code{request} is +performed until @code{item} is found. + +@example +(ews-get :GET request) + @result{} "/" + ;; Effect: Only the first line of the request is parsed. +(ews-get "foo" request) + @result{} "bar" + ;; Effect: Parameters are parsed until one named "foo" is + ;; found or no more parameters are left. +@end example +@end defun @node Usage Examples, Hello World, Request Headers, Top @chapter Usage Examples diff --git a/emacs-web-server-test.el b/emacs-web-server-test.el index 5649c91..3f16b1d 100644 --- a/emacs-web-server-test.el +++ b/emacs-web-server-test.el @@ -5,9 +5,6 @@ ;; Author: Eric Schulte <schulte.e...@gmail.com> ;; License: GPLV3 (see the COPYING file in this directory) -;; TODO: Allow running all tests at once, or just run tests in two -;; different Emacs instances. - ;;; Code: (require 'emacs-web-server) (require 'cl-lib) diff --git a/emacs-web-server.el b/emacs-web-server.el index baf2e62..23e6cbf 100644 --- a/emacs-web-server.el +++ b/emacs-web-server.el @@ -16,7 +16,7 @@ (require 'cl-lib) (defclass ews-server () - ((handler :initarg :handler :accessor handler :initform nil) + ((handlers :initarg :handlers :accessor handlers :initform nil) (process :initarg :process :accessor process :initform nil) (port :initarg :port :accessor port :initform nil) (clients :initarg :clients :accessor clients :initform nil))) @@ -32,10 +32,10 @@ (defvar ews-time-format "%Y.%m.%d.%H.%M.%S.%N" "Logging time format passed to `format-time-string'.") -(defun ews-start (handler port &optional log-buffer &rest network-args) - "Start a server using HANDLER and return the server object. +(defun ews-start (handlers port &optional log-buffer &rest network-args) + "Start a server using HANDLERS and return the server object. -HANDLER should be a list of cons of the form (MATCH . ACTION), +HANDLERS should be a list of cons of the form (MATCH . ACTION), where MATCH is either a function (in which case it is called on the request object) or a cons cell of the form (KEYWORD . STRING) in which case STRING is matched against the value of the header @@ -70,7 +70,7 @@ function. 8080) " - (let ((server (make-instance 'ews-server :handler handler :port port)) + (let ((server (make-instance 'ews-server :handlers handlers :port port)) (log (when log-buffer (get-buffer-create log-buffer)))) (setf (process server) (apply @@ -145,13 +145,13 @@ function. (ews-trim (substring string (match-end 0))))))) (defun ews-filter (proc string) - (with-slots (handler clients) (plist-get (process-plist proc) :server) + (with-slots (handlers clients) (plist-get (process-plist proc) :server) (unless (assoc proc clients) (push (cons proc (make-instance 'ews-client)) clients)) (let ((c (cdr (assoc proc clients)))) (when (not (eq (catch 'close-connection (if (ews-parse-request proc c string) - (ews-call-handler proc (cdr (headers c)) handler) + (ews-call-handler proc (cdr (headers c)) handlers) :keep-open)) :keep-open)) (setq clients (assq-delete-all proc clients)) @@ -219,7 +219,7 @@ deleted." (setq leftover (ews-trim (substring pending last-index))) nil)))) -(defun ews-call-handler (proc request handler) +(defun ews-call-handler (proc request handlers) (catch 'matched-handler (mapc (lambda (handler) (let ((match (car handler)) @@ -233,7 +233,7 @@ deleted." (condition-case e (funcall function proc request) (error (ews-error proc "Caught Error: %S" e))))))) - handler) + handlers) (ews-error proc "no handler matched request: %S" request))) (defun ews-error (proc msg &rest args) @@ -249,6 +249,19 @@ deleted." (apply #'ews-send-500 proc msg args))) +;;; Lazy request access functions +(defun ews-get (item request) + "Get ITEM from Request. +Perform any pending parsing of REQUEST until ITEM is found. This +is equivalent to calling (cdr (assoc ITEM (ews-alist REQUEST))) +except that once ITEM is found no further parsing is performed." + ) + +(defun ews-alist (request) + "Finish parsing REQUEST and return the resulting alist." + ) + + ;;; Convenience functions to write responses (defun ews-response-header (proc code &rest header) "Send the headers for an HTTP response to PROC.