@@ -3,14 +3,17 @@ module Test.Main where
33import Prelude
44
55import Data.Foldable (foldMap )
6- import Data.Maybe (Maybe (..))
6+ import Data.Maybe (Maybe (..), fromMaybe )
77import Data.Options (Options , options , (:=))
8+ import Data.Tuple (Tuple (..))
89import Effect (Effect )
910import Effect.Console (log , logShow )
11+ import Foreign.Object (fromFoldable , lookup )
1012import 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 )
1214import Node.HTTP.Client as Client
1315import Node.HTTP.Secure as HTTPS
16+ import Node.Net.Socket as Socket
1417import Node.Stream (Writable , end , pipe , writeString )
1518import Partial.Unsafe (unsafeCrashWith )
1619import Unsafe.Coerce (unsafeCoerce )
@@ -20,6 +23,7 @@ foreign import stdout :: forall r. Writable r
2023main :: Effect Unit
2124main = 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\n Content-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\n Content-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