Reject ranges that start beyond last item

This commit is contained in:
Joe Nelson
2014-09-07 12:47:07 -07:00
parent db7ccda74d
commit fcdc37d20b
4 changed files with 33 additions and 13 deletions
+10 -8
View File
@@ -99,11 +99,11 @@ respondWithRangedResult rr =
responseLBS status [
jsonContentType,
("Content-Range",
if rrTotal rr == 0
then "*/0"
else (BS.pack $ show from) <> "-"
<> (BS.pack $ show to) <> "/"
<> (BS.pack $ show total)
if total == 0 || from > total
then "*/" <> BS.pack (show total)
else BS.pack (show from) <> "-"
<> BS.pack (show to) <> "/"
<> BS.pack (show total)
)
] (rrBody rr)
@@ -111,9 +111,11 @@ respondWithRangedResult rr =
from = rrFrom rr
to = rrTo rr
total = rrTotal rr
status = if total == 0 then status204
else if (1 + to - from) < total then status206
else status200
status
| from > total = status416
| total == 0 = status204
| (1 + to - from) < total = status206
| otherwise = status200
requestedVersion :: RequestHeaders -> Maybe Int
requestedVersion hdrs =
+2 -2
View File
@@ -29,7 +29,7 @@ data RangedResult = RangedResult {
, rrTo :: Int
, rrTotal :: Int
, rrBody :: BL.ByteString
}
} deriving (Show)
type QuotedSql = (String, [SqlValue])
@@ -44,7 +44,7 @@ getRows schema table qq range conn = do
r <- quickQuery conn query []
return $ case r of
[[_, _, SqlNull]] -> RangedResult 0 0 0 ""
[[total, _, SqlNull]] -> RangedResult offset 0 (fromSql total) ""
[[total, limited_total, json]] ->
RangedResult offset (offset + fromSql limited_total - 1)
(fromSql total) (fromSql json)
+1 -1
View File
@@ -49,4 +49,4 @@ offset :: NonnegRange -> Int
offset range =
case rangeLower range
of BoundaryBelow from -> from
_ -> 0 -- should never happen
_ -> error "range without lower bound" -- should never happen
+20 -2
View File
@@ -39,11 +39,29 @@ spec = around appWithFixture $
`shouldRespondWith` ResponseMatcher {
matchBody = Nothing
, matchStatus = 204
, matchHeaders = []
, matchHeaders = [("Content-Range", "*/0")]
}
context "of invalid range" $
context "of invalid range" $ do
it "fails with 416 for offside range" $
request methodGet "/items"
(rangeHdrs $ ByteRangeFromTo 1 0) ""
`shouldRespondWith` 416
it "refuses a range with nonzero start when there are no items" $
request methodGet "/menagerie"
(rangeHdrs $ ByteRangeFromTo 1 2) ""
`shouldRespondWith` ResponseMatcher {
matchBody = Nothing
, matchStatus = 416
, matchHeaders = [("Content-Range", "*/0")]
}
it "refuses a range requesting start past last item" $
request methodGet "/items"
(rangeHdrs $ ByteRangeFromTo 100 199) ""
`shouldRespondWith` ResponseMatcher {
matchBody = Nothing
, matchStatus = 416
, matchHeaders = [("Content-Range", "*/15")]
}