@@ -1,5 +1,5 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2−module WaiExtraSpec where
2+module WaiExtraSpec (spec, toRequest) where
4import Test.Hspec
4import Test.Hspec
5import Test.HUnit hiding (Test)
5import Test.HUnit hiding (Test)
@@ -7,7 +7,6 @@ import Data.Monoid (mappend, mempty, (<>))
8import Network.Wai
8import Network.Wai
9import Network.Wai.Test
9import Network.Wai.Test
10−import Network.Wai.Parse
11import Network.Wai.UrlMap
10import Network.Wai.UrlMap
12import qualified Data.ByteString as S
11import qualified Data.ByteString as S
13import qualified Data.ByteString.Char8 as S8
12import qualified Data.ByteString.Char8 as S8
@@ -16,7 +15,6 @@ import qualified Data.Text.Lazy as T
16import qualified Data.Text as TS
15import qualified Data.Text as TS
17import qualified Data.Text.Encoding as TE
16import qualified Data.Text.Encoding as TE
18import Control.Applicative
17import Control.Applicative
19−import Control.Monad.Trans.Resource (withInternalState, runResourceT)
21import Network.Wai.Middleware.Jsonp
19import Network.Wai.Middleware.Jsonp
22import Network.Wai.Middleware.Gzip
20import Network.Wai.Middleware.Gzip
@@ -32,7 +30,6 @@ import Control.Monad.IO.Class (liftIO)
32import Data.Maybe (fromMaybe)
30import Data.Maybe (fromMaybe)
33import Network.HTTP.Types (parseSimpleQuery, status200)
31import Network.HTTP.Types (parseSimpleQuery, status200)
34import System.Log.FastLogger
32import System.Log.FastLogger
35−import System.IO (withFile, IOMode (ReadMode))
37import qualified Data.IORef as I
34import qualified Data.IORef as I
@@ -41,21 +38,9 @@ spec = do
41 describe "Network.Wai.UrlMap" $ do
38 describe "Network.Wai.UrlMap" $ do
42 mapM_ (uncurry it) casesUrlMap
39 mapM_ (uncurry it) casesUrlMap
44− describe "Network.Wai.Parse" $ do
41+ describe "Network.Wai" $ do
45− describe "parseContentType" $ do
46− let go (x, y, z) = it (TS.unpack $ TE.decodeUtf8 x) $ parseContentType x `shouldBe` (y, z)
48− [ ("text/plain", "text/plain", [])
49− , ("text/plain; charset=UTF-8 ", "text/plain", [("charset", "UTF-8")])
50− , ("text/plain; charset=UTF-8 ; boundary = foo", "text/plain", [("charset", "UTF-8"), ("boundary", "foo")])
52 it "parseQueryString" caseParseQueryString
42 it "parseQueryString" caseParseQueryString
53 it "parseQueryString with question mark" caseParseQueryStringQM
43 it "parseQueryString with question mark" caseParseQueryStringQM
54− it "parseHttpAccept" caseParseHttpAccept
55− it "parseRequestBody" caseParseRequestBody
56− it "multipart with plus" caseMultipartPlus
57− it "multipart with multiple attributes" caseMultipartAttrs
58− it "urlencoded with plus" caseUrlEncPlus
60 , it "findBound" caseFindBound
45 , it "findBound" caseFindBound
61 , it "sinkTillBound" caseSinkTillBound
46 , it "sinkTillBound" caseSinkTillBound
@@ -73,9 +58,6 @@ spec = do
73 it "method override" caseMethodOverride
58 it "method override" caseMethodOverride
74 it "method override post" caseMethodOverridePost
59 it "method override post" caseMethodOverridePost
75 it "accept override" caseAcceptOverride
60 it "accept override" caseAcceptOverride
76− describe "dalvik multipart" $ do
77− it "non-chunked" $ dalvikHelper True
78− it "chunked" $ dalvikHelper False
79 it "debug request body" caseDebugRequestBody
61 it "debug request body" caseDebugRequestBody
81caseParseQueryString :: Assertion
63caseParseQueryString :: Assertion
@@ -108,123 +90,6 @@ caseParseQueryStringQM = do
108 go [("/", "")] "%2f"
90 go [("/", "")] "%2f"
109 go [("foo bar", "")] "foo+bar"
91 go [("foo bar", "")] "foo+bar"
111−caseParseHttpAccept :: Assertion
112−caseParseHttpAccept = do
113− 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"
114− expected = ["text/html;charset=utf-8", "text/x-c", "text/x-dvi", "text/*", "text/plain"]
115− expected @=? parseHttpAccept input
117−parseRequestBody' :: BackEnd file
119− -> IO ([(S.ByteString, S.ByteString)], [(S.ByteString, FileInfo file)])
120−parseRequestBody' sink (SRequest req bod) =
121− case getRequestBodyType req of
122− Nothing -> return ([], [])
124− ref <- I.newIORef $ L.toChunks bod
125− let rb = I.atomicModifyIORef ref $ \chunks ->
129− sinkRequestBody sink rbt rb
131−caseParseRequestBody :: Assertion
132−caseParseRequestBody =
137− "Content-Disposition: form-data; name=\"document\"; filename=\"b.txt\"\n" <>
138− "Content-Type: text/plain; charset=iso-8859-1\n\n" <>
139− "This is a file.\n" <>
140− "It has two lines.\n" <>
142− "Content-Disposition: form-data; name=\"title\"\n" <>
143− "Content-Type: text/plain; charset=iso-8859-1\n\n" <>
146− "Content-Disposition: form-data; name=\"summary\"\n" <>
147− "Content-Type: text/plain; charset=iso-8859-1\n\n" <>
148− "This is my file\n" <>
151− content3 = "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\nContent-Disposition: form-data; name=\"yaml\"; filename=\"README\"\r\nContent-Type: application/octet-stream\r\n\r\nPhoto blog using Hack.\n\r\n------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
153− let content1 = "foo=bar&baz=bin"
154− let ctype1 = "application/x-www-form-urlencoded"
155− result1 <- parseRequestBody' lbsBackEnd $ toRequest ctype1 content1
156− assertEqual "parsing post x-www-form-urlencoded"
157− ([("foo", "bar"), ("baz", "bin")], [])
160− let ctype2 = "multipart/form-data; boundary=AaB03x"
161− result2 <- parseRequestBody' lbsBackEnd $ toRequest ctype2 content2
163− [ ("title", "A File")
164− , ("summary", "This is my file\nfile test")
166− let textPlain = "text/plain; charset=iso-8859-1"
168− [("document", FileInfo "b.txt" textPlain "This is a file.\nIt has two lines.")]
169− let expected2 = (expectedsmap2, expectedfile2)
170− assertEqual "parsing post multipart/form-data"
174− let ctype3 = "multipart/form-data; boundary=----WebKitFormBoundaryB1pWXPZ6lNr8RiLh"
175− result3 <- parseRequestBody' lbsBackEnd $ toRequest ctype3 content3
176− let expectedsmap3 = []
177− let expectedfile3 = [("yaml", FileInfo "README" "application/octet-stream" "Photo blog using Hack.\n")]
178− let expected3 = (expectedsmap3, expectedfile3)
179− assertEqual "parsing actual post multipart/form-data"
183− result2' <- parseRequestBody' lbsBackEnd $ toRequest' ctype2 content2
184− assertEqual "parsing post multipart/form-data 2"
188− result3' <- parseRequestBody' lbsBackEnd $ toRequest' ctype3 content3
189− assertEqual "parsing actual post multipart/form-data 2"
193−caseMultipartPlus :: Assertion
194−caseMultipartPlus = do
195− result <- parseRequestBody' lbsBackEnd $ toRequest ctype content
196− result @?= ([("email", "has+plus")], [])
200− "Content-Disposition: form-data; name=\"email\"\n" <>
201− "Content-Type: text/plain; charset=iso-8859-1\n\n" <>
204− ctype = "multipart/form-data; boundary=AaB03x"
206−caseMultipartAttrs :: Assertion
207−caseMultipartAttrs = do
208− result <- parseRequestBody' lbsBackEnd $ toRequest ctype content
209− result @?= ([("email", "has+plus")], [])
213− "Content-Disposition: form-data; name=\"email\"\n" <>
214− "Content-Type: text/plain; charset=iso-8859-1\n\n" <>
217− ctype = "multipart/form-data; charset=UTF-8; boundary=AaB03x"
219−caseUrlEncPlus :: Assertion
221− result <- runResourceT $ withInternalState $ \state ->
222− parseRequestBody' (tempFileBackEnd state) $ toRequest ctype content
223− result @?= ([("email", "has+plus")], [])
225− content = "email=has%2Bplus"
226− ctype = "application/x-www-form-urlencoded"
228toRequest :: S8.ByteString -> S8.ByteString -> SRequest
93toRequest :: S8.ByteString -> S8.ByteString -> SRequest
229toRequest ctype content = SRequest defaultRequest
94toRequest ctype content = SRequest defaultRequest
230 { requestHeaders = [("Content-Type", ctype)]
95 { requestHeaders = [("Content-Type", ctype)]
@@ -234,11 +99,6 @@ toRequest ctype content = SRequest defaultRequest
234 , queryString = []
99 , queryString = []
235 } (L.fromChunks [content])
100 } (L.fromChunks [content])
237−toRequest' :: S8.ByteString -> S8.ByteString -> SRequest
238−toRequest' ctype content = SRequest defaultRequest
239− { requestHeaders = [("Content-Type", ctype)]
240− } (L.fromChunks $ map S.singleton $ S.unpack content)
243caseFindBound :: Assertion
103caseFindBound :: Assertion
244caseFindBound = do
104caseFindBound = do
@@ -487,41 +347,6 @@ caseAcceptOverride = flip runSession aoApp $ do
488 assertHeader "Accept" "baz" sres3
348 assertHeader "Accept" "baz" sres3
490−dalvikHelper :: Bool -> Assertion
491−dalvikHelper includeLength = do
493− [ ("content-type", "multipart/form-data;boundary=*****")
494− , ("GATEWAY_INTERFACE", "CGI/1.1")
495− , ("PATH_INFO", "/")
496− , ("QUERY_STRING", "")
497− , ("REMOTE_ADDR", "192.168.1.115")
498− , ("REMOTE_HOST", "ganjizza")
499− , ("REQUEST_URI", "http://192.168.1.115:3000/")
500− , ("REQUEST_METHOD", "POST")
501− , ("HTTP_CONNECTION", "Keep-Alive")
502− , ("HTTP_COOKIE", "_SESSION=fgUGM5J/k6mGAAW+MMXIJZCJHobw/oEbb6T17KQN0p9yNqiXn/m/ACrsnRjiCEgqtG4fogMUDI+jikoFGcwmPjvuD5d+MDz32iXvDdDJsFdsFMfivuey2H+n6IF6yFGD")
503− , ("HTTP_USER_AGENT", "Dalvik/1.1.0 (Linux; U; Android 2.1-update1; sdk Build/ECLAIR)")
504− , ("HTTP_HOST", "192.168.1.115:3000")
505− , ("HTTP_ACCEPT", "*, */*")
506− , ("HTTP_VERSION", "HTTP/1.1")
507− , ("REQUEST_PATH", "/")
510− | includeLength = ("content-length", "12098") : headers'
511− | otherwise = headers'
512− let request' = defaultRequest
513− { requestHeaders = headers
516− case getRequestBodyType request' of
517− Nothing -> return ([], [])
518− Just rbt -> withFile "test/requests/dalvik-request" ReadMode $ \h ->
519− sinkRequestBody lbsBackEnd rbt $ S.hGetSome h 2048
520− lookup "scannedTime" params @?= Just "1.298590056748E9"
521− lookup "geoLong" params @?= Just "0"
522− lookup "geoLat" params @?= Just "0"
525caseDebugRequestBody :: Assertion
350caseDebugRequestBody :: Assertion
526caseDebugRequestBody = do
351caseDebugRequestBody = do
527 flip runSession (debugApp postOutput) $ do
352 flip runSession (debugApp postOutput) $ do