@@ -2,16 +2,18 @@ module Test.Main where
2
2
3
3
import Prelude
4
4
5
- import Data.Foldable (foldMap )
5
+ import Data.Either (Either (..))
6
+ import Data.Foldable (foldMap , for_ )
6
7
import Data.Maybe (fromMaybe )
7
8
import Effect (Effect )
9
+ import Effect.Aff (launchAff_ , makeAff , nonCanceler )
10
+ import Effect.Class (liftEffect )
8
11
import Effect.Console (log , logShow )
9
12
import Effect.Uncurried (EffectFn2 )
10
13
import Foreign.Object (lookup )
11
- import Node.Buffer (Buffer )
12
14
import Node.Buffer as Buffer
13
15
import Node.Encoding (Encoding (..))
14
- import Node.EventEmitter (once_ )
16
+ import Node.EventEmitter (once , once_ )
15
17
import Node.HTTP as HTTP
16
18
import Node.HTTP.ClientRequest as Client
17
19
import Node.HTTP.IncomingMessage as IM
@@ -23,7 +25,8 @@ import Node.HTTP.Types (HttpServer', IMServer, IncomingMessage, ServerResponse)
23
25
import Node.HTTPS as HTTPS
24
26
import Node.Net.Server (listenTcp )
25
27
import Node.Net.Server as NetServer
26
- import Node.Stream (Duplex , Writable , end , pipe )
28
+ import Node.Net.Socket as Socket
29
+ import Node.Stream (Writable , end , pipe )
27
30
import Node.Stream as Stream
28
31
import Partial.Unsafe (unsafeCrashWith )
29
32
import Unsafe.Coerce (unsafeCoerce )
@@ -35,7 +38,7 @@ foreign import stdout :: forall r. Writable r
35
38
main :: Effect Unit
36
39
main = do
37
40
testBasic
38
- -- testUpgrade
41
+ testUpgrade
39
42
testHttpsServer
40
43
testHttps
41
44
testCookies
@@ -195,44 +198,60 @@ logResponse response = void do
195
198
pipe (IM .toReadable response) stdout
196
199
197
200
testUpgrade :: Effect Unit
198
- testUpgrade = do
199
- server <- HTTP .createServer
200
- server # once_ Server .upgradeH handleUpgrade
201
-
202
- server # once_ Server .requestH (respond (mempty))
201
+ testUpgrade = launchAff_ do
202
+ server <- liftEffect HTTP .createServer
203
203
let netServer = Server .toNetServer server
204
- netServer # once_ NetServer .listeningH do
205
- log $ " Listening on port " <> show httpPort <> " ."
206
- sendRequests
207
- listenTcp netServer { host: " localhost" , port: httpPort }
204
+ waitUntilListening netServer
205
+
206
+ -- This tests that the upgrade callback is not called when the request is not an HTTP upgrade
207
+ doRegularRequest server
208
+
209
+ -- These two requests test that the upgrade callback is called and that it has
210
+ -- access to the original request and can write to the underlying TCP socket
211
+ checkUpgradeRequest server
212
+ checkWebSocketUpgrade server
213
+
214
+ liftEffect do
215
+ closeAllConnections server
216
+ NetServer .close netServer
208
217
where
209
218
httpPort = 3000
210
219
211
- handleUpgrade :: IncomingMessage IMServer -> Duplex -> Buffer -> Effect Unit
212
- handleUpgrade req socket _ = do
213
- let upgradeHeader = fromMaybe " " $ lookup " upgrade" $ IM .headers req
214
- if upgradeHeader == " websocket" then
215
- void $ Stream .writeString socket UTF8
216
- " HTTP/1.1 101 Switching Protocols\r\n Content-Length: 0\r\n\r\n "
217
- else
218
- void $ Stream .writeString socket UTF8
219
- " HTTP/1.1 426 Upgrade Required\r\n Content-Length: 0\r\n\r\n "
220
+ waitUntilListening netServer = makeAff \done -> do
221
+ netServer # once_ NetServer .listeningH do
222
+ liftEffect $ log $ " Listening on port " <> show httpPort <> " ."
223
+ done $ Right unit
224
+ listenTcp netServer { host: " localhost" , port: httpPort }
225
+ pure nonCanceler
226
+
227
+ doRegularRequest server = makeAff \done -> do
228
+ rmListener <- server # once Server .upgradeH \_ _ _ -> do
229
+ unsafeCrashWith " testUpgrade - regularRequest - got an upgrade request when expected simple request"
230
+ server # once_ Server .requestH (respond mempty)
220
231
221
- sendRequests :: Effect Unit
222
- sendRequests = do
223
- -- This tests that the upgrade callback is not called when the request is not an HTTP upgrade
224
232
reqSimple <- HTTP .requestOpts { port: httpPort }
225
233
reqSimple # once_ Client .responseH \response -> do
226
234
if (IM .statusCode response /= 200 ) then
227
- unsafeCrashWith " Unexpected response to simple request on `testUpgrade`"
228
- else
229
- pure unit
235
+ unsafeCrashWith $ " testUpgrade - regularRequest - unexpected response to simple request: " <> show (IM .statusCode response)
236
+ else do
237
+ rmListener
238
+ log " testUpgrade - regularRequest - Got regular response."
239
+ done $ Right unit
230
240
end (OM .toWriteable $ Client .toOutgoingMessage reqSimple)
241
+ pure nonCanceler
242
+
243
+ checkUpgradeRequest server = makeAff \done -> do
244
+ rmListener <- server # once Server .requestH \_ -> do
245
+ unsafeCrashWith " testUpgrade - checkUpgradeRequest - request handler fired instead of upgrade handler"
246
+ server # once_ Server .upgradeH \req socket _ -> do
247
+ case fromMaybe " " $ lookup " upgrade" $ IM .headers req of
248
+ " websocket" ->
249
+ unsafeCrashWith " testUpgrade - checkUpgradeRequest - expected non-websocket upgrade but got websocket upgrade"
250
+ _ -> do
251
+ void $ Stream .writeString (Socket .toDuplex socket) UTF8
252
+ " HTTP/1.1 426 Upgrade Required\r\n Content-Length: 0\r\n\r\n "
253
+ void $ Stream .end (Socket .toDuplex socket)
231
254
232
- {-
233
- These two requests test that the upgrade callback is called and that it has
234
- access to the original request and can write to the underlying TCP socket
235
- -}
236
255
reqUpgrade <- HTTP .requestOpts
237
256
{ port: httpPort
238
257
, headers: unsafeCoerce
@@ -242,10 +261,25 @@ testUpgrade = do
242
261
}
243
262
reqUpgrade # once_ Client .responseH \response -> do
244
263
if (IM .statusCode response /= 426 ) then
245
- unsafeCrashWith " Unexpected response to upgrade request on `testUpgrade`"
246
- else
247
- pure unit
264
+ unsafeCrashWith $ " Unexpected response to upgrade request on `testUpgrade`: " <> show (IM .statusCode response)
265
+ else do
266
+ rmListener
267
+ log " testUpgrade - checkUpgradeRequest - Got upgrade required response."
268
+ done $ Right unit
248
269
end (OM .toWriteable $ Client .toOutgoingMessage reqUpgrade)
270
+ pure nonCanceler
271
+
272
+ checkWebSocketUpgrade server = makeAff \done -> do
273
+ rmListener <- server # once Server .requestH \_ -> do
274
+ unsafeCrashWith " testUpgrade - checkWebSocketUpgrade - request handler fired instead of upgrade handler"
275
+ server # once_ Server .upgradeH \req socket _ -> do
276
+ case fromMaybe " " $ lookup " upgrade" $ IM .headers req of
277
+ " websocket" -> do
278
+ void $ Stream .writeString (Socket .toDuplex socket) UTF8
279
+ " HTTP/1.1 101 Switching Protocols\r\n Content-Length: 0\r\n\r\n "
280
+ void $ Stream .end (Socket .toDuplex socket)
281
+ _ ->
282
+ unsafeCrashWith " testUpgrade - checkWebSocketUpgrade - expected websocket upgrade but got non-websocket upgrade"
249
283
250
284
reqWSUpgrade <- HTTP .requestOpts
251
285
{ port: httpPort
@@ -257,6 +291,15 @@ testUpgrade = do
257
291
reqWSUpgrade # once_ Client .responseH \response -> do
258
292
if (IM .statusCode response /= 101 ) then
259
293
unsafeCrashWith " Unexpected response to websocket upgrade request on `testUpgrade`"
260
- else
261
- pure unit
294
+ else do
295
+ rmListener
296
+ mbSocket <- IM .socket response
297
+ for_ mbSocket \socket -> do
298
+ log " Destroying socket"
299
+ Stream .destroy (Socket .toDuplex socket)
300
+ log " testUpgrade - checkWebSocketUpgrade - Successfully upgraded to websocket."
301
+ done $ Right unit
302
+
262
303
end (OM .toWriteable $ Client .toOutgoingMessage reqWSUpgrade)
304
+ pure nonCanceler
305
+
0 commit comments