3 | import Derive.Prelude
4 | import HTTP.Parser.URI
5 | import HTTP.Parser.Util
8 | %hide Data.Linear.(.)
10 | %language ElabReflection
13 | data QueryVal : Type where
14 | QVal : (v : ByteString) -> QueryVal
17 | %runElab derive "QueryVal" [Show,Eq]
21 | Queries = List (ByteString,QueryVal)
27 | scheme : Maybe ByteString
28 | authority : Maybe ByteString
30 | path : List ByteString
32 | fragment : Maybe ByteString
34 | %runElab derive "URI" [Show,Eq]
36 | toQueries : ByteString -> Queries
37 | toQueries = map qpair . split byte_ampersand
39 | qpair : ByteString -> (ByteString, QueryVal)
41 | case break (byte_equals ==) bs of
42 | (pre, BS (S k) bv) => (pre, QVal $
BS k $
tail bv)
43 | (pre, _) => (pre, QEmpty)
45 | encodeQueries : Queries -> List ByteString
46 | encodeQueries [] = []
47 | encodeQueries ps = "?" :: intersperse "&" (map qpair ps)
49 | qpair : (ByteString, QueryVal) -> ByteString
51 | let en := uriEscape (not . isQueryNameByte) n
54 | QVal x => fastConcat [en,"=",uriEscape (not . isQueryByte) x]
57 | toURI (P sch auth abs segs ques frag) =
58 | MkURI sch auth abs (segs <>> []) (maybe empty toQueries ques) frag
60 | pathLines : URI -> List ByteString
61 | pathLines (MkURI s a abs p q f) =
62 | (if abs || not (null a || null p) then ["/"] else [])
63 | ++ intersperse "/" (map (uriEscape (not . ispchar)) p)
66 | encodePath : URI -> ByteString
67 | encodePath = fastConcat . pathLines
72 | encodeURI : URI -> ByteString
73 | encodeURI u@(MkURI s a _ _ q f) =
75 | maybe [] (::[":"]) s
76 | ++ maybe [] (\x => ["//", uriEscape (not . isAuthByte) x]) a
79 | ++ maybe [] (\x => ["#", uriEscape (not . isFragmentByte) x]) f
82 | parseURI : Origin -> ByteString -> Either (ParseError Void) URI
83 | parseURI o = map toURI . parseBytes uri o
86 | Interpolation URI where
87 | interpolate = toString . encodeURI
94 | testParseURI : ByteString -> IO ()
96 | either (putStrLn . interpolate) (putStrLn . interpolate) . parseURI Virtual