emacs-elpa-diffs
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]