-*- 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