29
33
import qualified Data.Conduit as C
30
34
import qualified Data.Conduit.List as CL
31
import Data.Conduit.Binary (sourceFile)
35
import Data.Conduit.Binary (sourceHandle)
32
36
import Control.Monad.IO.Class (liftIO)
33
37
import Data.Maybe (fromMaybe)
34
38
import Network.HTTP.Types (parseSimpleQuery, status200)
35
39
import System.Log.FastLogger
40
import System.IO (withFile, IOMode (ReadMode))
37
42
import qualified Data.IORef as I
46
describe "Network.Wai.UrlMap" $ do
47
mapM_ (uncurry it) casesUrlMap
41
49
describe "Network.Wai.Parse" $ do
42
50
describe "parseContentType" $ do
43
51
let go (x, y, z) = it (TS.unpack $ TE.decodeUtf8 x) $ parseContentType x `shouldBe` (y, z)
113
122
expected = ["text/html;charset=utf-8", "text/x-c", "text/x-dvi", "text/*", "text/plain"]
114
123
expected @=? parseHttpAccept input
116
parseRequestBody' :: BackEnd L.ByteString
125
parseRequestBody' :: BackEnd file
118
-> C.ResourceT IO ([(S.ByteString, S.ByteString)], [(S.ByteString, FileInfo L.ByteString)])
127
-> IO ([(S.ByteString, S.ByteString)], [(S.ByteString, FileInfo file)])
119
128
parseRequestBody' sink (SRequest req bod) =
120
129
case getRequestBodyType req of
121
130
Nothing -> return ([], [])
318
328
[("Content-Type", "text/plain")]
331
-- Lie a little and don't compress the body. This way we test
332
-- that the compression is skipped based on the presence of
333
-- the Content-Encoding header.
334
gzipPrecompressedApp :: Application
335
gzipPrecompressedApp = gzip def $ const $ return $ responseLBS status200
336
[("Content-Type", "text/plain"), ("Content-Encoding", "gzip")]
321
339
caseGzip :: Assertion
322
340
caseGzip = flip runSession gzipApp $ do
323
341
sres1 <- request defaultRequest
353
371
assertNoHeader "Content-Encoding" sres1
354
372
liftIO $ simpleBody sres1 @?= "test"
374
caseGzipBypassPre :: Assertion
375
caseGzipBypassPre = flip runSession gzipPrecompressedApp $ do
376
sres1 <- request defaultRequest
377
{ requestHeaders = [("Accept-Encoding", "gzip")]
379
assertHeader "Content-Encoding" "gzip" sres1
380
assertBody "test" sres1 -- the body is not actually compressed
356
382
vhostApp1, vhostApp2, vhostApp :: Application
357
383
vhostApp1 = const $ return $ responseLBS status200 [] "app1"
358
384
vhostApp2 = const $ return $ responseLBS status200 [] "app2"
360
[ ((== "foo.com") . serverName, vhostApp1)
386
[ ((== Just "foo.com") . lookup "host" . requestHeaders, vhostApp1)
364
390
caseVhost :: Assertion
365
391
caseVhost = flip runSession vhostApp $ do
366
392
sres1 <- request defaultRequest
367
{ serverName = "foo.com"
393
{ requestHeaders = [("Host", "foo.com")]
369
395
assertBody "app1" sres1
371
397
sres2 <- request defaultRequest
372
{ serverName = "bar.com"
398
{ requestHeaders = [("Host", "bar.com")]
374
400
assertBody "app2" sres2
493
519
(params, files) <-
494
520
case getRequestBodyType request' of
495
521
Nothing -> return ([], [])
496
Just rbt -> C.runResourceT $ sourceFile "test/requests/dalvik-request"
497
C.$$ sinkRequestBody lbsBackEnd rbt
522
Just rbt -> withFile "test/requests/dalvik-request" ReadMode $ \h ->
523
sourceHandle h C.$$ sinkRequestBody lbsBackEnd rbt
498
524
lookup "scannedTime" params @?= Just "1.298590056748E9"
499
525
lookup "geoLong" params @?= Just "0"
500
526
lookup "geoLat" params @?= Just "0"
520
546
params = [("foo", "bar"), ("baz", "bin")]
521
547
-- FIXME change back once we include post parameter output in logging postOutput = T.pack $ "POST \nAccept: \nPOST " ++ (show params)
522
postOutput = T.pack $ "POST /\nAccept: \nStatus: 200 OK. /\n"
523
getOutput params' = T.pack $ "GET /location\nAccept: \nGET " ++ show params' ++ "\nStatus: 200 OK. /location\n"
548
postOutput = T.pack $ "POST / :: \nStatus: 200 OK. /\n"
549
getOutput params' = T.pack $ "GET /location :: \nGET " ++ show params' ++ "\nStatus: 200 OK. /location\n"
525
551
debugApp output' req = do
526
iactual <- liftIO $ I.newIORef []
552
iactual <- liftIO $ I.newIORef mempty
527
553
middleware <- liftIO $ mkRequestLogger def
528
{ destination = Callback $ \strs -> I.modifyIORef iactual $ (++ strs)
554
{ destination = Callback $ \strs -> I.modifyIORef iactual $ (`mappend` strs)
529
555
, outputFormat = Detailed False
531
557
res <- middleware (\_req -> return $ responseLBS status200 [ ] "") req
532
558
actual <- liftIO $ I.readIORef iactual
533
liftIO $ assertEqual "debug" output $ logsToBs actual
559
liftIO $ assertEqual "debug" output $ logToBs actual
536
562
output = TE.encodeUtf8 $ T.toStrict output'
537
logsToBs = S.concat . map logToBs
540
logToBs (LS s) = S8.pack s
542
566
{-debugApp = debug $ \req -> do-}
543
567
{-return $ responseLBS status200 [ ] ""-}
569
urlMapTestApp :: Application
570
urlMapTestApp = mapUrls $
572
<|> mount "helpdesk" helpdeskApp
577
<|> mountRoot mainApp
580
trivialApp :: S.ByteString -> Application
581
trivialApp name req =
585
[ ("content-type", "text/plain")
586
, ("X-pathInfo", S8.pack . show . pathInfo $ req)
587
, ("X-rawPathInfo", rawPathInfo req)
588
, ("X-appName", name)
592
bugsApp = trivialApp "bugs"
593
helpdeskApp = trivialApp "helpdesk"
594
apiV1 = trivialApp "apiv1"
595
apiV2 = trivialApp "apiv2"
596
mainApp = trivialApp "main"
598
casesUrlMap :: [(String, Assertion)]
599
casesUrlMap = [pair1, pair2, pair3, pair4]
601
makePair name session = (name, runSession session urlMapTestApp)
602
get reqPath = request $ setPath defaultRequest reqPath
603
s = S8.pack . show :: [TS.Text] -> S.ByteString
605
pair1 = makePair "should mount root" $ do
607
assertStatus 200 res1
608
assertHeader "X-rawPathInfo" "/" res1
609
assertHeader "X-pathInfo" (s []) res1
610
assertHeader "X-appName" "main" res1
612
pair2 = makePair "should mount apps" $ do
614
assertStatus 200 res2
615
assertHeader "X-rawPathInfo" "/" res2
616
assertHeader "X-pathInfo" (s []) res2
617
assertHeader "X-appName" "bugs" res2
619
pair3 = makePair "should preserve extra path info" $ do
620
res3 <- get "/helpdesk/issues/11"
621
assertStatus 200 res3
622
assertHeader "X-rawPathInfo" "/issues/11" res3
623
assertHeader "X-pathInfo" (s ["issues", "11"]) res3
625
pair4 = makePair "should 404 if none match" $ do
626
res4 <- get "/api/v3"
627
assertStatus 404 res4