Skip to content

Commit

Permalink
Don't prematurly stop parsing
Browse files Browse the repository at this point in the history
Allow to parse a valid URI even if there's junk at the end.
  • Loading branch information
hasufell committed Dec 30, 2024
1 parent fc987cb commit fc2bd4a
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 14 deletions.
16 changes: 7 additions & 9 deletions src/URI/ByteString/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,11 @@ c8 = BB.fromChar
-- >>> parseURI myLaxOptions "http://www.example.org/foo?bar[]=baz"
-- Right (URI {uriScheme = Scheme {schemeBS = "http"}, uriAuthority = Just (Authority {authorityUserInfo = Nothing, authorityHost = Host {hostBS = "www.example.org"}, authorityPort = Nothing}), uriPath = "/foo", uriQuery = Query {queryPairs = [("bar[]","baz")]}, uriFragment = Nothing})
parseURI :: URIParserOptions -> ByteString -> Either URIParseError (URIRef Absolute)
parseURI opts = parseOnly' OtherError (uriParser' opts)
parseURI opts = parseOnly' OtherError (uriParser' opts <* Parser' endOfInput)

-- | Like 'parseURI', but do not parse scheme.
parseRelativeRef :: URIParserOptions -> ByteString -> Either URIParseError (URIRef Relative)
parseRelativeRef opts = parseOnly' OtherError (relativeRefParser' opts)
parseRelativeRef opts = parseOnly' OtherError (relativeRefParser' opts <* Parser' endOfInput)

-------------------------------------------------------------------------------

Expand All @@ -370,6 +370,8 @@ type URIParser = Parser' URIParseError
-------------------------------------------------------------------------------

-- | Underlying attoparsec parser. Useful for composing with your own parsers.
--
-- May not consume all input. You may want to combine it with @endOfInput@.
uriParser :: URIParserOptions -> Parser (URIRef Absolute)
uriParser = unParser' . uriParser'

Expand All @@ -383,14 +385,13 @@ uriParser' opts = do
(authority, path) <- hierPartParser
query <- queryParser opts
frag <- mFragmentParser
case frag of
Just _ -> endOfInput `orFailWith` MalformedFragment
Nothing -> endOfInput `orFailWith` MalformedQuery
return $ URI scheme authority path query frag

-------------------------------------------------------------------------------

-- | Underlying attoparsec parser. Useful for composing with your own parsers.
--
-- May not consume all input. You may want to combine it with @endOfInput@.
relativeRefParser :: URIParserOptions -> Parser (URIRef Relative)
relativeRefParser = unParser' . relativeRefParser'

Expand All @@ -402,9 +403,6 @@ relativeRefParser' opts = do
(authority, path) <- relativePartParser
query <- queryParser opts
frag <- mFragmentParser
case frag of
Just _ -> endOfInput `orFailWith` MalformedFragment
Nothing -> endOfInput `orFailWith` MalformedQuery
return $ RelativeRef authority path query frag

-------------------------------------------------------------------------------
Expand Down Expand Up @@ -619,7 +617,7 @@ queryParser opts = do
Just c
| c == question -> skip' 1 *> itemsParser
| c == hash -> pure mempty
| otherwise -> fail' MalformedPath
| otherwise -> pure mempty
_ -> pure mempty
where
itemsParser = Query . filter neQuery <$> A.sepBy' (queryItemParser opts) (word8' ampersand)
Expand Down
10 changes: 5 additions & 5 deletions test/URI/ByteStringTests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ parseUriTests =
"/foo"
mempty
(Just ""),
testParseFailure "http://www.example.org/foo#bar#baz" MalformedFragment,
testParseFailure "https://www.example.org?listParam[]=foo,bar" MalformedQuery,
testParseFailure "http://www.example.org/foo#bar#baz" (OtherError "endOfInput"),
testParseFailure "https://www.example.org?listParam[]=foo,bar" (OtherError "endOfInput"),
testParsesLax "https://www.example.org?listParam[]=foo,bar" $
URI
(Scheme "https")
Expand Down Expand Up @@ -201,9 +201,9 @@ parseUriTests =
(Query [])
Nothing,
parseTestURI strictURIParserOptions "file:///foo/%F" $
Left MalformedPath,
Left (OtherError "endOfInput"),
parseTestURI strictURIParserOptions "file:///foo/?foo=%F" $
Left MalformedQuery,
Left (OtherError "endOfInput"),
roundtripTestURI strictURIParserOptions "ftp://ftp.is.co.za/rfc/rfc1808.txt",
roundtripTestURI strictURIParserOptions "http://www.ietf.org/rfc/rfc2396.txt",
roundtripTestURI strictURIParserOptions "mailto:[email protected]",
Expand All @@ -219,7 +219,7 @@ parseUriTests =
(Query [])
Nothing,
parseTestRelativeRef strictURIParserOptions "this:that/thap/sub?1=2" $
Left $ MalformedPath,
Left (OtherError "endOfInput"),
parseTestRelativeRef strictURIParserOptions "./this:that/thap/sub?1=2" $
Right $
RelativeRef
Expand Down

0 comments on commit fc2bd4a

Please sign in to comment.