branch: externals/websocket
commit 542c6fec7447119c681d2a87da90a40223a81a36
Author: Andrew Hyatt <ahy...@gmail.com>
Commit: Andrew Hyatt <ahy...@gmail.com>

    Add support for cookies handling for ws clients.
    
    The url-cookie package is used to both supply cookie headers, and to
    parse them from the server.
---
 websocket-test.el | 71 +++++++++++++++++++++++++++++++++++++++++--------------
 websocket.el      | 30 +++++++++++++++++++----
 2 files changed, 78 insertions(+), 23 deletions(-)

diff --git a/websocket-test.el b/websocket-test.el
index 59e5aaa79b..7068bd0672 100644
--- a/websocket-test.el
+++ b/websocket-test.el
@@ -198,24 +198,59 @@
                               "Connection: Upgrade\r\n"
                               "Sec-WebSocket-Key: key\r\n"
                               "Sec-WebSocket-Version: 13\r\n")))
-    (should (equal (concat base-headers "\r\n")
-                   (websocket-create-headers "ws://www.example.com/path"
-                                             "key" nil nil)))
-    (should (equal (concat base-headers
-                           "Sec-WebSocket-Protocol: protocol\r\n\r\n")
-                   (websocket-create-headers "ws://www.example.com/path"
-                                             "key" '("protocol") nil)))
-    (should (equal
-             (concat base-headers
-                     "Sec-WebSocket-Extensions: ext1; a; b=2, ext2\r\n\r\n")
-             (websocket-create-headers "ws://www.example.com/path"
-                                       "key" nil
-                                       '(("ext1" . ("a" "b=2"))
-                                         ("ext2"))))))
-  (should
-   (string-match
-    "Host: www.example.com:123\r\n"
-    (websocket-create-headers "ws://www.example.com:123/path" "key" nil nil))))
+    (flet ((url-cookie-generate-header-lines
+            (host localpart secure) ""))
+      (should (equal (concat base-headers "\r\n")
+                     (websocket-create-headers "ws://www.example.com/path"
+                                               "key" nil nil)))
+      (should (equal (concat base-headers
+                             "Sec-WebSocket-Protocol: protocol\r\n\r\n")
+                     (websocket-create-headers "ws://www.example.com/path"
+                                               "key" '("protocol") nil)))
+      (should (equal
+               (concat base-headers
+                       "Sec-WebSocket-Extensions: ext1; a; b=2, ext2\r\n\r\n")
+               (websocket-create-headers "ws://www.example.com/path"
+                                         "key" nil
+                                         '(("ext1" . ("a" "b=2"))
+                                           ("ext2"))))))
+    (flet ((url-cookie-generate-header-lines
+            (host localpart secure)
+            (should (equal host "www.example.com:123"))
+            (should (equal localpart "/path"))
+            (should secure)
+            "Cookie: foo=bar\r\n"))
+      (should (equal (websocket-create-headers "wss://www.example.com:123/path"
+                                               "key" nil nil)
+                     (concat
+                      "Host: www.example.com:123\r\n"
+                      "Upgrade: websocket\r\n"
+                      "Connection: Upgrade\r\n"
+                      "Sec-WebSocket-Key: key\r\n"
+                      "Sec-WebSocket-Version: 13\r\n"
+                      "Cookie: foo=bar\r\n\r\n"))))
+    (should
+     (string-match
+      "Host: www.example.com:123\r\n"
+      (websocket-create-headers "ws://www.example.com:123/path" "key" nil 
nil)))))
+
+(ert-deftest websocket-process-headers ()
+  (flet ((url-cookie-handle-set-cookie
+          (text)
+          (should (equal text "foo=bar;"))
+          ;; test that we have set the implicit buffer variable needed
+          ;; by url-cookie-handle-set-cookie
+          (should (equal url-current-object
+                         (url-generic-parse-url "ws://example.com/path")))))
+    (websocket-process-headers "ws://example.com/path"
+                               (concat
+                                "HTTP/1.1 101 Switching Protocols\r\n"
+                                "Upgrade: websocket\r\n"
+                                "Connection: Upgrade\r\n"
+                                "Set-Cookie: foo=bar;\r\n\r\n")))
+  (flet ((url-cookie-handle-set-cookie (text) (should nil)))
+    (websocket-process-headers "ws://example.com/path"
+                               "HTTP/1.1 101 Switching Protocols\r\n")))
 
 (ert-deftest websocket-process-frame ()
   (let* ((sent)
diff --git a/websocket.el b/websocket.el
index f147383eb2..075bf5f74b 100644
--- a/websocket.el
+++ b/websocket.el
@@ -45,6 +45,7 @@
 
 (require 'bindat)
 (require 'url-parse)
+(require 'url-cookie)
 (eval-when-compile (require 'cl))
 
 ;;; Code:
@@ -611,6 +612,11 @@ The parameter strings are of the form \"key=value\" or 
\"value\".
 EXTENSIONS can be NIL if none are in use.  An example value would
 be '(\"deflate-stream\" . (\"mux\" \"max-channels=4\")).
 
+Cookies that are set via `url-cookie-store' will be used during
+communication with the server, and cookies received from the
+server will be stored in the same cookie storage that the
+`url-cookie' package uses.
+
 Optionally you can specify
 ON-OPEN, ON-MESSAGE and ON-CLOSE callbacks as well.
 
@@ -721,6 +727,14 @@ describing the problem with the frame.
     (websocket-debug websocket "Websocket opened")
     websocket))
 
+(defun websocket-process-headers (url headers)
+  "On opening URL, process the HEADERS sent from the server."
+  (when (string-match "Set-Cookie: \(.*\)\r\n" headers)
+    ;; The url-current-object is assumed to be set by
+    ;; url-cookie-handle-set-cookie.
+    (let ((url-current-object (url-generic-parse-url url)))
+      (url-cookie-handle-set-cookie (match-string 1 headers)))))
+
 (defun websocket-outer-filter (websocket output)
   "Filter the WEBSOCKET server's OUTPUT.
 This will parse headers and process frames repeatedly until there
@@ -739,7 +753,8 @@ connection is invalid, the connection will be closed."
       (condition-case err
           (progn
             (websocket-verify-response-code text)
-            (websocket-verify-headers websocket text))
+            (websocket-verify-headers websocket text)
+            (websocket-process-headers (websocket-url websocket) text))
         (error
          (websocket-close websocket)
          (signal (car err) (cdr err))))
@@ -870,7 +885,13 @@ connection, which should be kept in order to pass to
 (defun websocket-create-headers (url key protocol extensions)
   "Create connections headers for the given URL, KEY, PROTOCOL and EXTENSIONS.
 These are defined as in `websocket-open'."
-  (let ((parsed-url (url-generic-parse-url url)))
+  (let* ((parsed-url (url-generic-parse-url url))
+         (host-port (if (url-port-if-non-default parsed-url)
+                        (format "%s:%s" (url-host parsed-url) (url-port 
parsed-url))
+                      (url-host parsed-url)))
+         (cookie-header (url-cookie-generate-header-lines
+                         host-port (car (url-path-and-query parsed-url))
+                         (equal (url-type parsed-url) "wss"))))
     (format (concat "Host: %s\r\n"
                     "Upgrade: websocket\r\n"
                     "Connection: Upgrade\r\n"
@@ -893,10 +914,9 @@ These are defined as in `websocket-open'."
                                   (when (cdr ext)
                                     (mapconcat 'identity (cdr ext) "; "))))
                                extensions ", ")))
+                    (when cookie-header cookie-header)
                     "\r\n")
-            (if (url-port-if-non-default parsed-url)
-                (format "%s:%s" (url-host parsed-url) (url-port parsed-url))
-              (url-host parsed-url))
+            host-port
             key
             protocol)))
 

Reply via email to