Skip to content

Commit

Permalink
Add support for cookies handling for ws clients.
Browse files Browse the repository at this point in the history
The url-cookie package is used to both supply cookie headers, and to
parse them from the server.
  • Loading branch information
ahyatt committed Jun 27, 2015
1 parent b7a1907 commit 542c6fe
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 23 deletions.
71 changes: 53 additions & 18 deletions websocket-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
30 changes: 25 additions & 5 deletions websocket.el
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

(require 'bindat)
(require 'url-parse)
(require 'url-cookie)
(eval-when-compile (require 'cl))

;;; Code:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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))))
Expand Down Expand Up @@ -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"
Expand All @@ -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)))

Expand Down

0 comments on commit 542c6fe

Please sign in to comment.