[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] 04/119: simple hello world server working
From: |
Eric Schulte |
Subject: |
[elpa] 04/119: simple hello world server working |
Date: |
Mon, 10 Mar 2014 16:56:39 +0000 |
eschulte pushed a commit to branch master
in repository elpa.
commit ba0efd393bf3323156d349104d16ade3e06b9735
Author: Eric Schulte <address@hidden>
Date: Wed Dec 18 00:14:27 2013 -0700
simple hello world server working
---
NOTES | 17 --------------
emacs-web-server.el | 62 +++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 50 insertions(+), 29 deletions(-)
diff --git a/NOTES b/NOTES
deleted file mode 100644
index 1d2c3b3..0000000
--- a/NOTES
+++ /dev/null
@@ -1,17 +0,0 @@
- -*- org -*-
-
-* Notes
-** Elements of a web server
-http://stackoverflow.com/questions/176409/how-to-build-a-simple-http-server-in-c
-
-#+begin_quote
-1. Get your basic TCP sockets layer running (listen on port/ports, accept
client connections and send/receive data).
-2. Implement a buffered reader so that you can read requests one line
(delimited by CRLF) at a time.
-3. Read the very first line. Parse out the method, the request version and the
path.
-4. Implement header parsing for the "Header: value" syntax. Don't forget
unfolding folded headers.
-5. Check the request method, content type and content size to determine how/if
the body will be read.
-6. Implement decoding of content based on content type.
-7. If you're going to support HTTP 1.1, implement things like "100 Continue",
keep-alive, chunked transfer.
-8. Add robustness/security measures like detecting incomplete requests,
limiting max number of clients etc.
-9. Shrink wrap your code and open-source it :)
-#+end_quote
diff --git a/emacs-web-server.el b/emacs-web-server.el
index 8c1ec6b..ef22032 100644
--- a/emacs-web-server.el
+++ b/emacs-web-server.el
@@ -16,17 +16,35 @@
(port :initarg :port :accessor port :initform nil)
(clients :initarg :clients :accessor clients :initform nil)))
+(defvar ews-servers nil
+ "List holding all ews servers.")
+
(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 host)
"Start a server using HANDLER and return the server object.
-HANDLER should be a list of cons of the form (MATCH . DO), where
-MATCH is either a function call on the URI or a regular
-expression which attempts to match the URI. In either case when
-MATCH returns non-nil, then DO is called on two arguments, the
-URI and any post data."
+HANDLER 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
+specified by KEYWORD. In either case when MATCH returns non-nil,
+then the function ACTION is called with two arguments, the
+process and the request object.
+
+For example, the following starts a simple hello-world server on
+port 8080.
+
+ (ews-start
+ '(((:GET . \".*\") .
+ (lambda (proc request)
+ (process-send-string proc
+ \"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nhello
world\r\n\")
+ t)))
+ 8080)
+
+"
(let ((server (make-instance 'ews-server :handler handler :port port)))
(setf (process server)
(make-network-process
@@ -47,10 +65,12 @@ URI and any post data."
(insert (format "%s\t%s\t%s\t%s"
(format-time-string ews-time-format)
(first c) (second c) message)))))))))
+ (push server ews-servers)
server))
(defun ews-stop (server)
"Stop SERVER."
+ (setq ews-servers (remove server ews-servers))
(mapc #'delete-process (append (mapcar #'car (clients server))
(list (process server)))))
@@ -71,14 +91,32 @@ URI and any post data."
(let* ((client (assoc proc clients)) ; clients are (proc pending headers)
(pending (concat (cadr client) string))
(last-index 0) index)
- ;; parse headers and append to client
- (while (setq index (string-match "\r\n" pending last-index))
- ;; double newline indicates no more headers
- (unless (= last-index index)
+ (catch 'finished-parsing-headers
+ ;; parse headers and append to client
+ (while (setq index (string-match "\r\n" pending last-index))
+ (when (= last-index index) ; double \r\n, done headers, call handler
+ (throw 'finished-parsing-headers
+ (when (ews-call-handler proc (cddr client) handler)
+ (setq clients (assq-delete-all proc clients))
+ (delete-process proc))))
(setcdr (last client)
- (ews-parse (substring pending last-index index))))
- (setq last-index (+ index 2)))
- (setcar (cdr client) (substring pending last-index)))))
+ (ews-parse (substring pending last-index index)))
+ (setq last-index (+ index 2)))
+ (setcar (cdr client) (substring pending last-index))))))
+
+(defun ews-call-handler (proc request handler)
+ (catch 'matched-handler
+ (mapc (lambda (handler)
+ (let ((match (car handler))
+ (function (cdr handler)))
+ (when (or (and (consp match)
+ (assoc (car match) request)
+ (string-match (cdr match)
+ (cdr (assoc (car match) request))))
+ (and (functionp match) (funcall match request)))
+ (throw 'matched-handler (funcall function proc request)))))
+ handler)
+ (error "[ews] no handler matched request:%S" request)))
(provide 'emacs-web-server)
;;; emacs-web-server.el ends here
- [elpa] branch master updated (f64a801 -> 4f28097), Eric Schulte, 2014/03/10
- [elpa] 02/119: logging support, Eric Schulte, 2014/03/10
- [elpa] 03/119: parsing HTTP headers, Eric Schulte, 2014/03/10
- [elpa] 01/119: initial commit, echo server working, Eric Schulte, 2014/03/10
- [elpa] 04/119: simple hello world server working,
Eric Schulte <=
- [elpa] 05/119: stub out (but don't write any) tests, Eric Schulte, 2014/03/10
- [elpa] 08/119: NOTES file for tasks and notes, Eric Schulte, 2014/03/10
- [elpa] 07/119: TODO: handle post data, Eric Schulte, 2014/03/10
- [elpa] 06/119: helper for HTTP headers, Eric Schulte, 2014/03/10
- [elpa] 09/119: parsing form data in POST, Eric Schulte, 2014/03/10
- [elpa] 11/119: more flexible network process creation, Eric Schulte, 2014/03/10
- [elpa] 10/119: some simple examples, Eric Schulte, 2014/03/10
- [elpa] 15/119: more lenient parsing of multipart forms, Eric Schulte, 2014/03/10
- [elpa] 12/119: compiling to .elc, Eric Schulte, 2014/03/10
- [elpa] 13/119: tasks, Eric Schulte, 2014/03/10