-*- org -*-
Currently two failing tests.
- [X] ws/simple-post returns “you said nil” instead of “you said foo”
- [X] ws/in-directory-p is failing because it assumes “/tmp” which doesn’t work on windows
- Content and Transfer encoding values http://www.iana.org/assignments/http-parameters/http-parameters.xhtml
- http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6
- http://en.wikipedia.org/wiki/Chunked_transfer_encoding
- http://tools.ietf.org/html/rfc1945#section-7.2
- http://tools.ietf.org/rfc/rfc1945.txt
Some issue as to whether compression is better done as a “Content Encoding” which actually changes the content, or as a “Transfer Encoding”, which doesn’t change the content, just the messages.
The latter seems preferable, but possibly less widely supported. See http://stackoverflow.com/questions/11641923/transfer-encoding-gzip-vs-content-encoding-gzip.
- content-coding
- compress
- Unix
compress
program (rfc2616) - deflate
zlib
(see http://www.iana.org/go/rfc1950) format withdefalte
compression (rfc2616)- exi
- W3c efficient XML (see http://www.w3.org/TR/exi/)
- gzip
- GNU zip (rfc2616)
- identity
- does nothing
- pack200-zip
- specific to Java archives (see http://www.jcp.org/en/jsr/detail?id=200)
- transfer-coding
- chunked
- (rfc2616)
- compress
- same as above
- deflate
- same as above
- gzip
- same as above
- tail-header
- Content-MD5
- Base64 encoded binary MD5 sum of content
Maybe we can set the coding system of the process with
define-coding-system
, specifically using the :pre-write-conversion
flag to e.g., gzip or chunkify the contents.
Already exists as part of org-ehtml. file:examples/011-org-agenda.el
Idea stolen from elnode. file:examples/010-current-buffer.el
file:examples/012-search-bbdb.el
- upload a file
- supply an export type
- return the exported version of the file
When large files arrive quickly, the filter functions are called while they are still running on the previous chunk, this leads to nasty race conditions for the state of the request object.
Either introduce some check to wait on new input if input is currently being parsed, or wait until all input has arrived before doing any parsing.
Now using an active
field on request objects to avoid race
conditions when new header text is received while the parsing function
is still active.
Low priority, just run behind a proxy.
- State “HOLD” from “TODO” [2014-02-10 Mon 19:06]
digest may not be worth it, just run Basic over HTTPS
http://en.wikipedia.org/wiki/Basic_access_authentication
http://en.wikipedia.org/wiki/Digest_access_authentication
If this is implemented, it would be good to implement some safeguards against common attacks.
- Server nonce is allowed to contain timestamps. Therefore the server may inspect nonce attributes submitted by clients, to prevent replay attacks.
- Server is also allowed to maintain a list of recently issued or used server nonce values to prevent reuse.
not sure if the extra performance is worth the added complexity
Before the header is fully parsed, call any potential handlers. Include a field in the request object to indicate that the request isn’t finished being received so handlers can return and wait to be called again.
Also, put a catch in the filter function and allow the headers
function on the request object to throw to said catch aborting the
handler and waiting for the rest of the input.
- [X] introduction
- [X] handlers
- [X] request headers
- [X] usage examples
- [X] list of functions
Notes to touch upon
- [X] how to set content type
- read standard for POST data
- parse multi-line headers with boundaries
For now keep this all incremental and in ws-filter.
- byte-compile
- package
- test
- benchmark
include an easy error handler like the 404 handler
parse more than just the content-type headers.
e.g., parameter strings
- [X] strip and parse URL query string
- [X] parse urlencoded post data
- [X] think about defaulting to (name . content) for form elements
- [X] maybe don’t require a non-nil return to cancel the connection,
instead only keep open if
:keep-alive
is returned - [X] function to send a file (with mime handling)
- [X] send a 404 with some default text
- State “CANCELED” from “TODO” [2013-12-25 Wed 12:21]
premature optimization
Use lazy sequence functions for header a-list to avoid parsing all headers. For regexp matchers should stop when matched header is encountered (often the first one when :GET), For function matchers provide lazy version of assoc.
Also, there is the issue of how a lazy request for more parameters
should act before all incoming text has been received. Emacs does not
provide a light-weight mechanism for a function to wait for incoming
process text without something gross like the (sit-for 0.1)
used in
the test suite.
low priority – just run behind an https proxy.
This will be a pain, and will require expanding info:emacs-gnutls to add support for starting server processes, currently only client processes are supported.
The following tutorials walk through common usage scenarios including
installing the Emacs web-server and running it behind a proxy.
Install the Emacs web-server and run (info "web-server")
to browse
the full manual within Emacs, or view the HTML version at
emacs-web-server.
Most easily installable through the GNU ELPA, run M-x
package-list-packages
select web-server
and install. Alternately,
install from the git repository at
https://github.com/eschulte/emacs-web-server and update your the load.
- Ensure that you have Emacs version 24 or greater installed.
emacs --version
GNU Emacs 24.3.1 Copyright (C) 2013 Free Software Foundation, Inc. GNU Emacs comes with ABSOLUTELY NO WARRANTY. You may redistribute copies of Emacs under the terms of the GNU General Public License. For more information about these matters, see the file named COPYING.
- Download and unpack the zip archive of the Emacs web-server code
from emacs-web-server-master.zip or clone the source code
repository with git.
git clone https://github.com/eschulte/emacs-web-server.git
- Move into the root of the
emacs-web-server/
directory and optionally runmake
to compile the web-server code, and runmake check
to test your web-server install.make make check
- From the root of the
emacs-web-server/
directory, start an instance of Emacs with web-server loaded.emacs -Q -L . -l web-server
Alternately, from an already running Emacs instance, add this directory to the load path and load the web server with the following.
(add-to-list 'load-path "path/to/emacs-web-server") (require 'web-server)
- Evaluate the following code in
*scratch*
buffer of this Emacs instance.(ws-start (lambda (request) (with-slots (process headers) request (ws-response-header process 200 '("Content-type" . "text/plain")) (process-send-string process "hello world"))) 9000)
- Browse to http://localhost:9000 to see that the web-server is running.
- Read the web-server manual and work through other Usage Examples.
Public-facing instance of the Emacs web-server should be run behind a more established web server such as Apache or Nginx to provide additional robustness and security.
The following example Apache configuration may be used to have a public facing Apache server listening on port 80 proxy requests to a local web-server instance running on port 8888 of the same machine.
<VirtualHost *:80>
ServerName yourserver.com
ProxyPass / http://localhost:8888/
</VirtualHost>
A similar Nginx configuration is available at http://wiki.nginx.org/LoadBalanceExample.
The following example configurations will cause Apache or Nginx to act as an HTTPS proxy for an instance of the Emacs web server running on the same machine. With this setup Apache speaks HTTPS to the outside world, and communicates with the Emacs web server using HTTP. This allows use of HTTPS even though the Emacs web server does not implement HTTPS itself. This setup is recommended for any setup, but should be considered required for sites using BASIC HTTP Authentication.
This requires that Apache has mod_proxy
and mod_ssl
enabled, and
that the certificate and key files required for SSL are present. This
these requirements satisfied, and assuming the Emacs web server is
listening on port 8888 and is running on the same machine as the
Apache web server an Apache virtual host configuration such as the
following.
<VirtualHost *:443>
ProxyPreserveHost On
ServerName yourserver.com
SSLEngine On
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
ProxyPass / http://localhost:8888/
ProxyPassReverse / http://localhost:8888/
</VirtualHost>
See the following for instructions configuring Nginx as an HTTPS proxy.
- http://wiki.nginx.org/SSL-Offloader#sslproxy.conf
- http://www.cyberciti.biz/faq/howto-linux-unix-setup-nginx-ssl-proxy/
- specifically servers with active client process
- maybe also implement a
ws-stop-all
function