-*- org -*-
#+Title: Notes and Tasks
#+HTML_HEAD:
#+Options: ^:{}
* Notes
* Tasks [19/22]
** DONE pass all tests on Windows [2/2]
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
** DONE Content and Transfer encodings
- 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 with
=defalte= 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.
** DONE web sockets
- http://en.wikipedia.org/wiki/WebSocket
- http://tools.ietf.org/html/rfc6455
** more examples [4/4]
*** DONE Org-mode agenda
Already exists as part of org-ehtml.
file:examples/011-org-agenda.el
*** DONE display the current buffer
Idea stolen from elnode.
file:examples/010-current-buffer.el
*** DONE browse the BBDB
file:examples/012-search-bbdb.el
*** DONE org-mode export server
1. upload a file
2. supply an export type
3. return the exported version of the file
** DONE handle large files
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.
** TODO robustness to bad requests [0/2]
Low priority, just [[*running%20behind%20a%20proxy][run behind a proxy]].
*** TODO request timeout
*** TODO maximum request size
** DONE authentication [2/2]
- State "HOLD" from "TODO" [2014-02-10 Mon 19:06] \\
digest may not be worth it, just run Basic over HTTPS
*** DONE Basic
http://en.wikipedia.org/wiki/Basic_access_authentication
*** CANCELED Digest
http://en.wikipedia.org/wiki/Digest_access_authentication
If this is implemented, it would be good to implement some safeguards
against common attacks.
#+begin_quote
- 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.
#+end_quote
** incremental handler calls
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.
** DONE Documentation [6/6]
- [X] introduction
- [X] handlers
- [X] request headers
- [X] usage examples
- [X] list of functions
Notes to touch upon
- [X] how to set content type
** DONE Handle POST requests
1. read standard for POST data
2. parse multi-line headers with boundaries
For now keep this all incremental and in ws-filter.
** DONE Makefile
- byte-compile
- package
- test
- benchmark
** DONE catch errors and return an error code
include an easy error handler like the 404 handler
** DONE better parsing of multipart form blocks
parse more than just the content-type headers.
** DONE non-multipart form data
e.g., parameter strings
** DONE some more convenience functionality [6/6]
- [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
** CANCELED Lazy header processing
- 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.
** use gnutls for https
low priority -- just [[*running%20behind%20an%20https%20proxy][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.
** screen cast?
- http://en.wikipedia.org/wiki/XVidCap
- https://aur.archlinux.org/packages/xvidcap/
* Tutorials
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
[[http://eschulte.github.io/emacs-web-server/][emacs-web-server]].
** Installation and running a 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.
1. Ensure that you have Emacs version 24 or greater installed.
#+begin_src sh :results scalar
emacs --version
#+end_src
: 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.
2. Download and unpack the zip archive of the Emacs web-server code
from [[https://github.com/eschulte/emacs-web-server/archive/master.zip][emacs-web-server-master.zip]] or clone the source code
repository with [[http://git-scm.com/][git]].
#+begin_src sh
git clone https://github.com/eschulte/emacs-web-server.git
#+end_src
3. Move into the root of the =emacs-web-server/= directory and
optionally run =make= to compile the web-server code, and run =make
check= to test your web-server install.
#+begin_src sh
make
make check
#+end_src
4. From the root of the =emacs-web-server/= directory, start an
instance of Emacs with web-server loaded.
#+begin_src sh
emacs -Q -L . -l web-server
#+end_src
Alternately, from an already running Emacs instance, add this
directory to the load path and load the web server with the
following.
#+begin_src emacs-lisp
(add-to-list 'load-path "path/to/emacs-web-server")
(require 'web-server)
#+end_src
5. Evaluate the following code in =*scratch*= buffer of this Emacs
instance.
#+begin_src emacs-lisp
(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)
#+end_src
6. Browse to http://localhost:9000 to see that the web-server is
running.
7. Read the web-server [[http://eschulte.github.io/emacs-web-server/index.html#Top][manual]] and work through other [[http://eschulte.github.io/emacs-web-server/Usage-Examples.html#Usage-Examples][Usage Examples]].
** Running behind a proxy
Public-facing instance of the Emacs web-server should be run behind a
more established web server such as [[http://httpd.apache.org/][Apache]] or [[http://wiki.nginx.org][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.
#+begin_src conf
ServerName yourserver.com
ProxyPass / http://localhost:8888/
#+end_src
A similar Nginx configuration is available at
http://wiki.nginx.org/LoadBalanceExample.
** Running behind an https proxy
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.
*** Apache
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.
#+begin_src conf
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/
#+end_src
*** Nginx
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/
** COMMENT documentation for running in a chroot jail
See https://wiki.archlinux.org/index.php/nginx#Installation_in_a_chroot.
* Bugs [1/1]
** DONE Sometimes servers don't stop cleanly
- specifically servers with active client process
- maybe also implement a =ws-stop-all= function