@@ -2,16 +2,18 @@ module Test.Main where
22
33import Prelude
44
5- import Data.Foldable (foldMap )
5+ import Data.Either (Either (..))
6+ import Data.Foldable (foldMap , for_ )
67import Data.Maybe (fromMaybe )
78import Effect (Effect )
9+ import Effect.Aff (launchAff_ , makeAff , nonCanceler )
10+ import Effect.Class (liftEffect )
811import Effect.Console (log , logShow )
912import Effect.Uncurried (EffectFn2 )
1013import Foreign.Object (lookup )
11- import Node.Buffer (Buffer )
1214import Node.Buffer as Buffer
1315import Node.Encoding (Encoding (..))
14- import Node.EventEmitter (once_ )
16+ import Node.EventEmitter (once , once_ )
1517import Node.HTTP as HTTP
1618import Node.HTTP.ClientRequest as Client
1719import Node.HTTP.IncomingMessage as IM
@@ -23,7 +25,8 @@ import Node.HTTP.Types (HttpServer', IMServer, IncomingMessage, ServerResponse)
2325import Node.HTTPS as HTTPS
2426import Node.Net.Server (listenTcp )
2527import 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 )
2730import Node.Stream as Stream
2831import Partial.Unsafe (unsafeCrashWith )
2932import Unsafe.Coerce (unsafeCoerce )
@@ -35,7 +38,7 @@ foreign import stdout :: forall r. Writable r
3538main :: Effect Unit
3639main = do
3740 testBasic
38- -- testUpgrade
41+ testUpgrade
3942 testHttpsServer
4043 testHttps
4144 testCookies
@@ -195,44 +198,60 @@ logResponse response = void do
195198 pipe (IM .toReadable response) stdout
196199
197200testUpgrade :: 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
203203 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
208217 where
209218 httpPort = 3000
210219
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)
220231
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
224232 reqSimple <- HTTP .requestOpts { port: httpPort }
225233 reqSimple # once_ Client .responseH \response -> do
226234 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
230240 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)
231254
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- -}
236255 reqUpgrade <- HTTP .requestOpts
237256 { port: httpPort
238257 , headers: unsafeCoerce
@@ -242,10 +261,25 @@ testUpgrade = do
242261 }
243262 reqUpgrade # once_ Client .responseH \response -> do
244263 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
248269 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"
249283
250284 reqWSUpgrade <- HTTP .requestOpts
251285 { port: httpPort
@@ -257,6 +291,15 @@ testUpgrade = do
257291 reqWSUpgrade # once_ Client .responseH \response -> do
258292 if (IM .statusCode response /= 101 ) then
259293 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+
262303 end (OM .toWriteable $ Client .toOutgoingMessage reqWSUpgrade)
304+ pure nonCanceler
305+
0 commit comments