eschulte pushed a commit to branch master in repository elpa. commit d1ad64c02c409376e9c002e8a2672bec1d1b9e0c Author: Eric Schulte <schulte.e...@gmail.com> Date: Thu Dec 26 13:17:59 2013 -0700
even more documentation and examples and an improved in-directory testing function --- doc/emacs-web-server.texi | 164 ++++++++++++++++++++++++++++++++++----------- emacs-web-server-test.el | 11 +++ emacs-web-server.el | 15 ++--- 3 files changed, 141 insertions(+), 49 deletions(-) diff --git a/doc/emacs-web-server.texi b/doc/emacs-web-server.texi index 30d79cf..4649474 100644 --- a/doc/emacs-web-server.texi +++ b/doc/emacs-web-server.texi @@ -43,7 +43,7 @@ A copy of the license is included in the section entitled @menu * Introduction:: Overview of the Emacs Web Server * Handlers:: Handlers respond to HTTP requests -* Request:: Getting information on HTTP requests +* Requests:: Getting information on HTTP requests * Usage Examples:: Examples demonstrating usage * Function Index:: List of Functions @@ -68,7 +68,7 @@ Appendices The Emacs Web Server is a Web server implemented entirely in Emacs Lisp. HTTP requests are matched to handlers (@pxref{Handlers}) which are Emacs Lisp functions. Handlers receive as their only argument a -request object (@pxref{Request}) which holds information about the +request object (@pxref{Requests}) which holds information about the request and the process holding HTTP network connection. Handlers write their responses directly to the network process. @@ -76,7 +76,7 @@ A number of examples (@pxref{Usage Examples}) demonstrate usage of the Emacs Web Server. All public functions of the Emacs Web Server are listed (@pxref{Function Index}). -@node Handlers, Request, Handlers, Top +@node Handlers, Requests, Handlers, Top @chapter Handlers @cindex handlers @@ -86,6 +86,7 @@ The function @code{ews-start} takes takes two arguments association list composed of pairs of matchers and handler functions. @section Matchers +@cindex matchers Matchers may be a regular expression or a function. Regular expression matchers consists of an HTTP header and a regular @@ -99,7 +100,7 @@ whose path starts with the substring ``foo''. @end example A function matcher is a function which takes the request object -(@pxref{Request}) and succeeds when the function returns a non-nil +(@pxref{Requests}) and succeeds when the function returns a non-nil value. For example the following matcher matches every request, @example @@ -114,10 +115,11 @@ and the following matches only requests in which the supplied (oddp (string-to-number (cdr (assoc "number" request))))) @end example -@section Handler +@section Handler Function +@cindex handler function Each handler is a function which takes a request object -(@pxref{Request}) as its only argument. The function may respond to +(@pxref{Requests}) as its only argument. The function may respond to the request by writing to the network process held in the @code{process} field of the request object. For example, the @code{process-send-string} function may be used to write string data @@ -130,20 +132,21 @@ to a request as in the following. When the handler function exits the connection is terminated unless the handler function returns the keyword @code{:keep-alive}. -@node Request, Usage Examples, Handlers, Top -@chapter Request -@cindex request +@node Requests, Usage Examples, Handlers, Top +@chapter Requests +@cindex requests -Each HTTP requests is represented using a @code{request} object. 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. +Each HTTP requests is represented using an @code{ews-request} object +(@pxref{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., @code{:GET}), and user supplied parameters are keyed using the string name of the parameter. -@node Usage Examples, Hello World, Request, Top +@node Usage Examples, Hello World, Requests, Top @chapter Usage Examples @cindex usage examples @@ -229,41 +232,117 @@ in a @code{POST} request. The following functions implement the Emacs Web Server public API. -To start and stop servers, use the following functions. +@section Objects +The following objects represent web servers and requests. + +@anchor{ews-server} +@deftp Class ews-server handlers process port requests +Every Emacs web server is an instance of the @code{ews-server} class. +Each instance includes the @code{handlers} association list and +@code{port} passed to @code{ews-start}, as well as the server network +@code{process} and a list of all active @code{requests}. +@end deftp + +@anchor{ews-request} +@deftp Class ews-request process pending context boundary headers +The @code{ews-request} class represents an active web request. The +@code{process} field holds the network process of the client machine +and may be used by handlers to respond to requests. The +@code{headers} field holds an alist of information on the request for +use by handlers. The remaining @code{pending}, @code{context} and +@code{boundary} fields are used to maintain header parsing information +across calls to the @code{ews-filter} function. +@end deftp + +@section Starting and Stopping Servers +@cindex start and stop +The following functions start and stop Emacs web servers. The +@code{ews-servers} list holds all running servers. + +@anchor{ews-start} +@defun ews-start handlers port &optional log-buffer &rest network-args +@code{ews-start} starts a server listening on @code{port} using +@code{handlers} (@pxref{Handlers}) to match and respond to requests. +An instance of the @code{ews-server} class is returned. +@end defun + +@anchor{ews-servers} +@defvar ews-servers +The @code{ews-servers} list holds all active Emacs web servers. +@end defvar + +@anchor{ews-stop} +@defun ews-stop server +@code{ews-stop} stops @code{server} deletes all related processes, and +frees the server's port. Evaluate the following to stop all emacs web +servers. +@example +(mapc #'ews-stop ews-servers) +@end example +@end defun -@itemize -@item ews-start -@item ews-stop -@end itemize +@section Convenience Functions +The following convenience functions automate many common tasks +associated with responding to HTTP requests. -All running servers are stored in the @code{ews-servers} variable. +@anchor{ews-response-header} +@cindex content type +@defun ews-response-header process code &rest header +Send the headers required to start an HTTP response to @code{process}. +@code{process} should be a @code{ews-request} @code{process} of an +active request. For example start a standard 200 ``OK'' HTML response +with the following. -@itemize -@item ews-servers -@end itemize +@example +(ews-response-header process 200 '("Content-type" . "text/html")) +@end example -Each ews-server is an instance of the @code{ews-server} class. +The encoding may optionally be set in the HTTP header. Send a UTF8 +encoded response with the following. -@itemize -@item ews-server -@end itemize +@example +(ews-response-header process 200 + '("Content-type" . "text/plain; charset=utf-8")) +@end example -Each request object is an instance of the @code{ews-client} class. +@end defun + +@anchor{ews-send-500} +@defun ews-send-500 process &rest msg-and-args +@code{ews-send-500} sends a default 500 ``Internal Server Error'' +response to @code{process}. +@end defun + +@anchor{ews-send-404} +@defun ews-send-404 process &rest msg-and-args +@code{ews-send-500} sends a default 404 ``File Not Found'' response to +@code{process}. +@end defun + +@anchor{ews-send-file} +@defun ews-send-file process path &optional mime-type +@code{ews-send-file} sends the file located at @code{path} to +@code{process}. If the optional @code{mime-type} is not set, then the +mime-type is determined by calling @code{mm-default-file-encoding} on +@code{path} or is set to ``application/octet-stream'' if no mime-type +can be determined. +@end defun + +@anchor{ews-in-directory-p} +@defun ews-in-directory-p parent path +Check if @code{path} is under the @code{parent} directory. -@itemize -@item ews-request -@end itemize +@example +(ews-in-directory-p "/tmp/" "pics") + @result{} "/tmp/pics" -The following convenience functions automate many common tasks -associated with responding to HTTP requests. +(ews-in-directory-p "/tmp/" "..") + @result{} nil -@itemize -@item ews-response-header -@item ews-send-500 -@item ews-send-404 -@item ews-send-file -@item ews-subdirectoryp -@end itemize +(ews-in-directory-p "/tmp/" "~/pics") + @result{} nil +@end example +@end defun @node Copying, GNU Free Documentation License, Function Index, Top @appendix GNU GENERAL PUBLIC LICENSE @@ -276,6 +355,11 @@ associated with responding to HTTP requests. @node Index, , GNU Free Documentation License, Top @unnumbered Index +@c Combine all index (function variable type and concept) types into a +@c single index. +@syncodeindex fn cp +@syncodeindex vr cp +@syncodeindex tp cp @printindex cp @bye diff --git a/emacs-web-server-test.el b/emacs-web-server-test.el index aa80442..6255ee6 100644 --- a/emacs-web-server-test.el +++ b/emacs-web-server-test.el @@ -179,4 +179,15 @@ org=-+one%0A-+two%0A-+three%0A-+four%0A%0A&beg=646&end=667&path=%2Fcomplex.org") (should (string= (ews-test-curl-to-string "" nil '(("message" . "foo"))) "you said \"foo\"\n")))) +(ert-deftest ews/in-directory-p () + (should-not (ews-in-directory-p "/tmp/" "foo/bar/../../../")) + (should (ews-in-directory-p "/tmp/" "foo/bar/../../../tmp/baz")) + (should (ews-in-directory-p "/tmp/" "./")) + (should-not (ews-in-directory-p "/tmp/" "/~/pics")) + (should-not (ews-in-directory-p "/tmp/" "~/pics")) + (should-not (ews-in-directory-p "/tmp/" "/pics")) + (should-not (ews-in-directory-p "/tmp/" "../pics")) + (should (ews-in-directory-p "/tmp/" "pics")) + (should-not (ews-in-directory-p "/tmp/" ".."))) + (provide 'emacs-web-server-test) diff --git a/emacs-web-server.el b/emacs-web-server.el index 29838f9..41d87fe 100644 --- a/emacs-web-server.el +++ b/emacs-web-server.el @@ -293,16 +293,13 @@ Optionally explicitly set MIME-TYPE, otherwise it is guessed by (insert-file-contents-literally path) (buffer-string))))) -(defun ews-subdirectoryp (parent path) - "Check that PATH is a subdirectory of PARENT. +(defun ews-in-directory-p (parent path) + "Check if PATH is under the PARENT directory. If so return PATH, if not return nil." - (let* ((expanded (expand-file-name path)) - (complete (if (string= (substring expanded -1) "/") - expanded - (concat expanded "/")))) - (and (>= (length complete) (length parent)) - (string= parent (substring complete 0 (length parent))) - complete))) + (let ((expanded (expand-file-name path parent))) + (and (>= (length expanded) (length parent)) + (string= parent (substring expanded 0 (length parent))) + expanded))) (provide 'emacs-web-server) ;;; emacs-web-server.el ends here