on master help sign in
Resolve #715: Add linkUri'
commitabb48a2713bba1e89a85f9f5abde8ffeb4cdc061 authorOleg Grenrus <oleg.grenrus@iki.fi> dateSun 14 May 2017, 19:53 (9 years ago) parent27facba
1 file changed+35−13
servant/src/Servant/Utils/Links.hs+35−13
servant/src/Servant/Utils/Links.hs+35−13
@@ -87,8 +87,14 @@ module Servant.Utils.Links (
8787 , URI(..)
8888 -- * Adding custom types
8989 , HasLink(..)
90− , linkURI
9190 , Link
91+ , linkURI
92+ , linkURI'
93+ , LinkArrayElementStyle (..)
94+ -- ** Link accessors
95+ , Param (..)
96+ , linkSegments
97+ , linkQueryParams
9298) where
9399
94100import Data.List
@@ -118,21 +124,24 @@ import Servant.API.Experimental.Auth ( AuthProtect )
118124-- The only way of constructing a 'Link' is using 'safeLink', which means any
119125-- 'Link' is guaranteed to be part of the mentioned API.
120126data Link = Link
121− { _segments :: [String] -- ^ Segments of "foo/bar" would be ["foo", "bar"]
122− , _queryParams :: [Param Query]
127+ { _segments :: [String] -- ^ Segments of "foo/bar" would be ["foo", "bar"]
128+ , _queryParams :: [Param]
123129 } deriving Show
124130
131+linkSegments :: Link -> [String]
132+linkSegments = _segments
133+
134+linkQueryParams :: Link -> [Param]
135+linkQueryParams = _queryParams
136+
125137instance ToHttpApiData Link where
126138 toHeader = TE.encodeUtf8 . toUrlPiece
127139 toUrlPiece l =
128140 let uri = linkURI l
129141 in Text.pack $ uriPath uri ++ uriQuery uri
130142
131−-- Phantom types for Param
132−data Query
133−
134−-- | Query param
135−data Param a
143+-- | Query parameter.
144+data Param
136145 = SingleParam String Text.Text
137146 | ArrayElemParam String Text.Text
138147 | FlagParam String
@@ -141,27 +150,40 @@ data Param a
141150addSegment :: String -> Link -> Link
142151addSegment seg l = l { _segments = _segments l <> [seg] }
143152
144−addQueryParam :: Param Query -> Link -> Link
153+addQueryParam :: Param -> Link -> Link
145154addQueryParam qp l =
146155 l { _queryParams = _queryParams l <> [qp] }
147156
148157linkURI :: Link -> URI
149−linkURI (Link segments q_params) =
158+linkURI = linkURI' LinkArrayElementBracket
159+
160+-- | How to encode array query elements.
161+data LinkArrayElementStyle
162+ = LinkArrayElementBracket -- ^ @foo[]=1&foo[]=2@
163+ | LinkArrayElementPlain -- ^ @foo=1&foo=2@
164+ deriving (Eq, Ord, Show, Enum, Bounded)
165+
166+linkURI' :: LinkArrayElementStyle -> Link -> URI
167+linkURI' addBrackets (Link segments q_params) =
150168 URI mempty -- No scheme (relative)
151169 Nothing -- Or authority (relative)
152170 (intercalate "/" segments)
153171 (makeQueries q_params) mempty
154172 where
155− makeQueries :: [Param Query] -> String
173+ makeQueries :: [Param] -> String
156174 makeQueries [] = ""
157175 makeQueries xs =
158176 "?" <> intercalate "&" (fmap makeQuery xs)
159177
160− makeQuery :: Param Query -> String
161− makeQuery (ArrayElemParam k v) = escape k <> "[]=" <> escape (Text.unpack v)
178+ makeQuery :: Param -> String
179+ makeQuery (ArrayElemParam k v) = escape k <> style <> escape (Text.unpack v)
162180 makeQuery (SingleParam k v) = escape k <> "=" <> escape (Text.unpack v)
163181 makeQuery (FlagParam k) = escape k
164182
183+ style = case addBrackets of
184+ LinkArrayElementBracket -> "[]="
185+ LinkArrayElementPlain -> "="
186+
165187escape :: String -> String
166188escape = escapeURIString isUnreserved
167189