Skip to content

Commit 48458d4

Browse files
VFabricioVilson Fabricio Juliatto
and
Vilson Fabricio Juliatto
authored
Add support for update events (#33)
* Add `onUpgrade` function (#32) * Add tests for `onUpgrade` * Update CI to 0.14.0-rc5 Co-authored-by: Vilson Fabricio Juliatto <fabricio@juliatto.com>
1 parent 1ff3ba9 commit 48458d4

File tree

5 files changed

+88
-3
lines changed

5 files changed

+88
-3
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414

1515
- uses: purescript-contrib/setup-purescript@main
1616
with:
17-
purescript: "0.14.0-rc3"
17+
purescript: "0.14.0-rc5"
1818

1919
- uses: actions/setup-node@v1
2020
with:

bower.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"purescript-foreign-object": "master",
2323
"purescript-maybe": "master",
2424
"purescript-node-buffer": "master",
25+
"purescript-node-net": "master",
2526
"purescript-node-streams": "master",
2627
"purescript-node-url": "master",
2728
"purescript-nullable": "main",

src/Node/HTTP.js

+10
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ exports.listenSocket = function (server) {
4646
};
4747
};
4848

49+
exports.onUpgrade = function (server) {
50+
return function (cb) {
51+
return function () {
52+
server.on("upgrade", function (req, socket, buffer) {
53+
return cb(req)(socket)(buffer)();
54+
});
55+
};
56+
};
57+
};
58+
4959
exports.setHeader = function (res) {
5060
return function (key) {
5161
return function (value) {

src/Node/HTTP.purs

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Node.HTTP
1010
, close
1111
, ListenOptions
1212
, listenSocket
13+
, onUpgrade
1314

1415
, httpVersion
1516
, requestHeaders
@@ -30,6 +31,8 @@ import Data.Maybe (Maybe)
3031
import Data.Nullable (Nullable, toNullable)
3132
import Effect (Effect)
3233
import Foreign.Object (Object)
34+
import Node.Buffer (Buffer)
35+
import Node.Net.Socket (Socket)
3336
import Node.Stream (Writable, Readable)
3437
import Unsafe.Coerce (unsafeCoerce)
3538

@@ -67,6 +70,9 @@ type ListenOptions =
6770
-- | Listen on a unix socket. The specified callback will be run when setup is complete.
6871
foreign import listenSocket :: Server -> String -> Effect Unit -> Effect Unit
6972

73+
-- | Listen to `upgrade` events on the server
74+
foreign import onUpgrade :: Server -> (Request -> Socket -> Buffer -> Effect Unit) -> Effect Unit
75+
7076
-- | Get the request HTTP version
7177
httpVersion :: Request -> String
7278
httpVersion = _.httpVersion <<< unsafeCoerce

test/Main.purs

+70-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ module Test.Main where
33
import Prelude
44

55
import Data.Foldable (foldMap)
6-
import Data.Maybe (Maybe(..))
6+
import Data.Maybe (Maybe(..), fromMaybe)
77
import Data.Options (Options, options, (:=))
8+
import Data.Tuple (Tuple(..))
89
import Effect (Effect)
910
import Effect.Console (log, logShow)
11+
import Foreign.Object (fromFoldable, lookup)
1012
import Node.Encoding (Encoding(..))
11-
import Node.HTTP (Request, Response, listen, createServer, setHeader, requestMethod, requestURL, responseAsStream, requestAsStream, setStatusCode)
13+
import Node.HTTP (Request, Response, listen, createServer, setHeader, requestHeaders, requestMethod, requestURL, responseAsStream, requestAsStream, setStatusCode, onUpgrade)
1214
import Node.HTTP.Client as Client
1315
import Node.HTTP.Secure as HTTPS
16+
import Node.Net.Socket as Socket
1417
import Node.Stream (Writable, end, pipe, writeString)
1518
import Partial.Unsafe (unsafeCrashWith)
1619
import Unsafe.Coerce (unsafeCoerce)
@@ -20,6 +23,7 @@ foreign import stdout :: forall r. Writable r
2023
main :: Effect Unit
2124
main = do
2225
testBasic
26+
testUpgrade
2327
testHttpsServer
2428
testHttps
2529
testCookies
@@ -154,3 +158,67 @@ logResponse response = void do
154158
log "Response:"
155159
let responseStream = Client.responseAsStream response
156160
pipe responseStream stdout
161+
162+
testUpgrade :: Effect Unit
163+
testUpgrade = do
164+
server <- createServer respond
165+
onUpgrade server handleUpgrade
166+
listen server { hostname: "localhost", port: 3000, backlog: Nothing }
167+
$ void do
168+
log "Listening on port 3000."
169+
sendRequests
170+
where
171+
handleUpgrade req socket buffer = do
172+
let upgradeHeader = fromMaybe "" $ lookup "upgrade" $ requestHeaders req
173+
if upgradeHeader == "websocket" then
174+
void $ Socket.writeString
175+
socket
176+
"HTTP/1.1 101 Switching Protocols\r\nContent-Length: 0\r\n\r\n"
177+
UTF8
178+
$ pure unit
179+
else
180+
void $ Socket.writeString
181+
socket
182+
"HTTP/1.1 426 Upgrade Required\r\nContent-Length: 0\r\n\r\n"
183+
UTF8
184+
$ pure unit
185+
186+
sendRequests = do
187+
-- This tests that the upgrade callback is not called when the request is not an HTTP upgrade
188+
reqSimple <- Client.request (Client.port := 3000) \response -> do
189+
if (Client.statusCode response /= 200) then
190+
unsafeCrashWith "Unexpected response to simple request on `testUpgrade`"
191+
else
192+
pure unit
193+
end (Client.requestAsStream reqSimple) (pure unit)
194+
{-
195+
These two requests test that the upgrade callback is called and that it has
196+
access to the original request and can write to the underlying TCP socket
197+
-}
198+
let headers = Client.RequestHeaders $ fromFoldable
199+
[ Tuple "Connection" "upgrade"
200+
, Tuple "Upgrade" "something"
201+
]
202+
reqUpgrade <- Client.request
203+
(Client.port := 3000 <> Client.headers := headers)
204+
\response -> do
205+
if (Client.statusCode response /= 426) then
206+
unsafeCrashWith "Unexpected response to upgrade request on `testUpgrade`"
207+
else
208+
pure unit
209+
end (Client.requestAsStream reqUpgrade) (pure unit)
210+
211+
let wsHeaders = Client.RequestHeaders $ fromFoldable
212+
[ Tuple "Connection" "upgrade"
213+
, Tuple "Upgrade" "websocket"
214+
]
215+
216+
reqWSUpgrade <- Client.request
217+
(Client.port := 3000 <> Client.headers := wsHeaders)
218+
\response -> do
219+
if (Client.statusCode response /= 101) then
220+
unsafeCrashWith "Unexpected response to websocket upgrade request on `testUpgrade`"
221+
else
222+
pure unit
223+
end (Client.requestAsStream reqWSUpgrade) (pure unit)
224+
pure unit

0 commit comments

Comments
 (0)