1
1
{-# LANGUAGE OverloadedStrings #-}
2
2
module WaiExtraTest (specs) where
4
import Test.Hspec.Monadic
5
import Test.Hspec.HUnit ()
6
5
import Test.HUnit hiding (Test)
13
12
import qualified Data.ByteString.Lazy.Char8 as L8
14
13
import qualified Data.ByteString.Lazy as L
15
14
import qualified Data.Text.Lazy as T
15
import qualified Data.Text as TS
16
16
import qualified Data.Text.Encoding as TE
17
17
import Control.Arrow
23
23
import Network.Wai.Middleware.MethodOverride
24
24
import Network.Wai.Middleware.MethodOverridePost
25
25
import Network.Wai.Middleware.AcceptOverride
26
import Network.Wai.Middleware.RequestLogger (logCallback)
26
import Network.Wai.Middleware.RequestLogger
27
27
import Codec.Compression.GZip (decompress)
29
29
import qualified Data.Conduit as C
32
32
import Control.Monad.IO.Class (liftIO)
33
33
import Data.Maybe (fromMaybe)
34
34
import Network.HTTP.Types (parseSimpleQuery, status200)
35
import System.Log.FastLogger
37
import qualified Data.IORef as I
38
41
describe "Network.Wai.Parse" $ do
42
describe "parseContentType" $ do
43
let go (x, y, z) = it (TS.unpack $ TE.decodeUtf8 x) $ parseContentType x `shouldBe` (y, z)
45
[ ("text/plain", "text/plain", [])
46
, ("text/plain; charset=UTF-8 ", "text/plain", [("charset", "UTF-8")])
47
, ("text/plain; charset=UTF-8 ; boundary = foo", "text/plain", [("charset", "UTF-8"), ("boundary", "foo")])
39
49
it "parseQueryString" caseParseQueryString
40
50
it "parseQueryString with question mark" caseParseQueryStringQM
41
51
it "parseHttpAccept" caseParseHttpAccept
42
52
it "parseRequestBody" caseParseRequestBody
53
it "multipart with plus" caseMultipartPlus
54
it "multipart with multiple attributes" caseMultipartAttrs
55
it "urlencoded with plus" caseUrlEncPlus
44
57
, it "findBound" caseFindBound
45
58
, it "sinkTillBound" caseSinkTillBound
55
68
it "method override" caseMethodOverride
56
69
it "method override post" caseMethodOverridePost
57
70
it "accept override" caseAcceptOverride
58
it "dalvik multipart" caseDalvikMultipart
71
describe "dalvik multipart" $ do
72
it "non-chunked" $ dalvikHelper True
73
it "chunked" $ dalvikHelper False
59
74
it "debug request body" caseDebugRequestBody
61
76
caseParseQueryString :: Assertion
94
109
caseParseHttpAccept :: Assertion
95
110
caseParseHttpAccept = do
96
let input = "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"
97
expected = ["text/html", "text/x-c", "text/x-dvi", "text/plain"]
111
let input = "text/plain; q=0.5, text/html;charset=utf-8, text/*;q=0.8;ext=blah, text/x-dvi; q=0.8, text/x-c"
112
expected = ["text/html;charset=utf-8", "text/x-c", "text/x-dvi", "text/*", "text/plain"]
98
113
expected @=? parseHttpAccept input
100
115
parseRequestBody' :: BackEnd L.ByteString
187
caseMultipartPlus :: Assertion
188
caseMultipartPlus = do
189
result <- C.runResourceT $ parseRequestBody' lbsBackEnd $ toRequest ctype content
190
liftIO $ result @?= ([("email", "has+plus")], [])
194
"Content-Disposition: form-data; name=\"email\"\n" ++
195
"Content-Type: text/plain; charset=iso-8859-1\n\n" ++
198
ctype = "multipart/form-data; boundary=AaB03x"
200
caseMultipartAttrs :: Assertion
201
caseMultipartAttrs = do
202
result <- C.runResourceT $ parseRequestBody' lbsBackEnd $ toRequest ctype content
203
liftIO $ result @?= ([("email", "has+plus")], [])
207
"Content-Disposition: form-data; name=\"email\"\n" ++
208
"Content-Type: text/plain; charset=iso-8859-1\n\n" ++
211
ctype = "multipart/form-data; charset=UTF-8; boundary=AaB03x"
213
caseUrlEncPlus :: Assertion
215
result <- C.runResourceT $ parseRequestBody' lbsBackEnd $ toRequest ctype content
216
liftIO $ result @?= ([("email", "has+plus")], [])
218
content = S8.pack $ "email=has%2Bplus"
219
ctype = "application/x-www-form-urlencoded"
172
221
toRequest :: S8.ByteString -> S8.ByteString -> SRequest
173
222
toRequest ctype content = SRequest defaultRequest
174
223
{ requestHeaders = [("Content-Type", ctype)]
406
455
assertHeader "Accept" "baz" sres3
408
caseDalvikMultipart :: Assertion
409
caseDalvikMultipart = do
411
[ ("content-length", "12098")
412
, ("content-type", "multipart/form-data;boundary=*****")
457
dalvikHelper :: Bool -> Assertion
458
dalvikHelper includeLength = do
460
[ ("content-type", "multipart/form-data;boundary=*****")
413
461
, ("GATEWAY_INTERFACE", "CGI/1.1")
414
462
, ("PATH_INFO", "/")
415
463
, ("QUERY_STRING", "")
425
473
, ("HTTP_VERSION", "HTTP/1.1")
426
474
, ("REQUEST_PATH", "/")
477
| includeLength = ("content-length", "12098") : headers'
478
| otherwise = headers'
428
479
let request' = defaultRequest
429
480
{ requestHeaders = headers
446
497
assertStatus 200 res
448
499
let qs = "?foo=bar&baz=bin"
449
flip runSession (debugApp $ getOutput qs) $ do
500
flip runSession (debugApp $ getOutput params) $ do
450
501
assertStatus 200 =<< request defaultRequest
451
502
{ requestMethod = "GET"
452
503
, queryString = map (\(k,v) -> (k, Just v)) params
458
509
params = [("foo", "bar"), ("baz", "bin")]
459
510
-- FIXME change back once we include post parameter output in logging postOutput = T.pack $ "POST \nAccept: \nPOST " ++ (show params)
460
postOutput = T.pack $ "POST / Accept: \nStatus: 200 OK"
461
-- FIXME getOutput _qs = T.pack $ "GET /location" ++ "\nAccept: \nGET " ++ (show params) -- \nAccept: \n" ++ (show params)
462
getOutput _qs = T.pack $ "GET /location?foo=bar&baz=bin Accept: \nStatus: 200 OK"
511
postOutput = T.pack $ "POST /\nAccept: \nStatus: 200 OK. /\n"
512
getOutput params' = T.pack $ "GET /location\nAccept: \nGET " ++ show params' ++ "\nStatus: 200 OK. /location\n"
464
debugApp output' = logCallback (\t -> liftIO $ assertEqual "debug" output t) $ \_req -> do
465
return $ responseLBS status200 [ ] ""
514
debugApp output' req = do
515
iactual <- liftIO $ I.newIORef []
516
middleware <- liftIO $ mkRequestLogger def
517
{ destination = Callback $ \strs -> I.modifyIORef iactual $ (++ strs)
518
, outputFormat = Detailed False
520
res <- middleware (\_req -> return $ responseLBS status200 [ ] "") req
521
actual <- liftIO $ I.readIORef iactual
522
liftIO $ assertEqual "debug" output $ logsToBs actual
467
525
output = TE.encodeUtf8 $ T.toStrict output'
526
logsToBs = S.concat . map logToBs
529
logToBs (LS s) = S8.pack s
468
531
{-debugApp = debug $ \req -> do-}
469
532
{-return $ responseLBS status200 [ ] ""-}