1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
{-# LANGUAGE OverloadedStrings #-}
module FileSpec (main, spec) where
import Data.ByteString
import Data.String (fromString)
import Network.HTTP.Types
import Network.Wai.Handler.Warp.File
import Network.Wai.Handler.Warp.FileInfoCache
import Network.Wai.Handler.Warp.Header
import System.IO.Unsafe (unsafePerformIO)
import Test.Hspec
main :: IO ()
main = hspec spec
changeHeaders
:: (ResponseHeaders -> ResponseHeaders) -> RspFileInfo -> RspFileInfo
changeHeaders f rfi =
case rfi of
WithBody s hs off len -> WithBody s (f hs) off len
other -> other
getHeaders :: RspFileInfo -> ResponseHeaders
getHeaders rfi =
case rfi of
WithBody _ hs _ _ -> hs
_ -> []
testFileRange
:: String
-> RequestHeaders
-> RspFileInfo
-> Spec
testFileRange desc reqhs ans = it desc $ do
finfo <- getInfo "attic/hex"
let f = (:) ("Last-Modified", fileInfoDate finfo)
hs = getHeaders ans
ans' = changeHeaders f ans
conditionalRequest
finfo
[]
methodGet
(indexResponseHeader hs)
(indexRequestHeader reqhs)
`shouldBe` ans'
farPast, farFuture :: ByteString
farPast = "Thu, 01 Jan 1970 00:00:00 GMT"
farFuture = "Sun, 05 Oct 3000 00:00:00 GMT"
regularBody :: RspFileInfo
regularBody = WithBody ok200 [("Content-Length", "16"), ("Accept-Ranges", "bytes")] 0 16
make206Body :: Integer -> Integer -> RspFileInfo
make206Body start len =
WithBody status206 [crHeader, lenHeader, ("Accept-Ranges", "bytes")] start len
where
lenHeader = ("Content-Length", fromString $ show len)
crHeader =
( "Content-Range"
, fromString $ "bytes " <> show start <> "-" <> show (start + len - 1) <> "/16"
)
spec :: Spec
spec = do
describe "conditionalRequest" $ do
testFileRange
"gets a file size from file system"
[]
regularBody
testFileRange
"gets a file size from file system and handles Range and returns Partical Content"
[("Range", "bytes=2-14")]
$ make206Body 2 13
testFileRange
"truncates end point of range to file size"
[("Range", "bytes=10-20")]
$ make206Body 10 6
testFileRange
"gets a file size from file system and handles Range and returns OK if Range means the entire"
[("Range:", "bytes=0-15")]
regularBody
testFileRange
"returns a 412 if the file has been changed in the meantime"
[("If-Unmodified-Since", farPast)]
$ WithoutBody status412
testFileRange
"gets a file if the file has not been changed in the meantime"
[("If-Unmodified-Since", farFuture)]
regularBody
testFileRange
"ignores the If-Unmodified-Since header if an If-Match header is also present"
[("If-Match", "SomeETag"), ("If-Unmodified-Since", farPast)]
regularBody
testFileRange
"still gives only a range, even after conditionals"
[ ("If-Match", "SomeETag")
, ("If-Unmodified-Since", farPast)
, ("Range", "bytes=10-20")
]
$ make206Body 10 6
testFileRange
"gets a file if the file has been changed in the meantime"
[("If-Modified-Since", farPast)]
regularBody
testFileRange
"returns a 304 if the file has not been changed in the meantime"
[("If-Modified-Since", farFuture)]
$ WithoutBody status304
testFileRange
"ignores the If-Modified-Since header if an If-None-Match header is also present"
[("If-None-Match", "SomeETag"), ("If-Modified-Since", farFuture)]
regularBody
testFileRange
"still gives only a range, even after conditionals"
[ ("If-None-Match", "SomeETag")
, ("If-Modified-Since", farFuture)
, ("Range", "bytes=10-13")
]
$ make206Body 10 4
testFileRange
"gives the a range, if the condition is met"
[ ("If-Range", fileInfoDate (unsafePerformIO $ getInfo "attic/hex"))
, ("Range", "bytes=2-7")
]
$ make206Body 2 6
testFileRange
"gives the entire body and ignores the Range header if the condition isn't met"
[("If-Range", farPast), ("Range", "bytes=2-7")]
regularBody
|