@@ -37,7 +37,7 @@ module Servant.API.ResponseHeaders
37
37
import Control.DeepSeq
38
38
(NFData (.. ))
39
39
import Data.ByteString.Char8 as BS
40
- (ByteString , init , pack , unlines )
40
+ (ByteString , pack )
41
41
import qualified Data.CaseInsensitive as CI
42
42
import qualified Data.List as L
43
43
import Data.Proxy
@@ -52,7 +52,7 @@ import Web.HttpApiData
52
52
import Prelude ()
53
53
import Prelude.Compat
54
54
import Servant.API.Header
55
- (Header )
55
+ (Header , Header' )
56
56
import Servant.API.UVerb.Union
57
57
import qualified Data.SOP.BasicFunctors as SOP
58
58
import qualified Data.SOP.NS as SOP
@@ -81,19 +81,19 @@ instance NFData a => NFData (ResponseHeader sym a) where
81
81
82
82
data HList a where
83
83
HNil :: HList '[]
84
- HCons :: ResponseHeader h x -> HList xs -> HList (Header h x ': xs )
84
+ HCons :: ResponseHeader h x -> HList xs -> HList (Header' mods h x ': xs )
85
85
86
86
class NFDataHList xs where rnfHList :: HList xs -> ()
87
87
instance NFDataHList '[] where rnfHList HNil = ()
88
- instance (y ~ Header h x , NFData x , NFDataHList xs ) => NFDataHList (y ': xs ) where
88
+ instance (y ~ Header' mods h x , NFData x , NFDataHList xs ) => NFDataHList (y ': xs ) where
89
89
rnfHList (HCons h xs) = rnf h `seq` rnfHList xs
90
90
91
91
instance NFDataHList xs => NFData (HList xs ) where
92
92
rnf = rnfHList
93
93
94
94
type family HeaderValMap (f :: * -> * ) (xs :: [* ]) where
95
95
HeaderValMap f '[] = '[]
96
- HeaderValMap f (Header h x ': xs ) = Header h (f x ) ': HeaderValMap f xs
96
+ HeaderValMap f (Header' mods h x ': xs ) = Header' mods h (f x ) ': HeaderValMap f xs
97
97
98
98
99
99
class BuildHeadersTo hs where
@@ -105,7 +105,7 @@ instance {-# OVERLAPPING #-} BuildHeadersTo '[] where
105
105
-- The current implementation does not manipulate HTTP header field lines in any way,
106
106
-- like merging field lines with the same field name in a single line.
107
107
instance {-# OVERLAPPABLE #-} ( FromHttpApiData v , BuildHeadersTo xs , KnownSymbol h )
108
- => BuildHeadersTo (Header h v ': xs ) where
108
+ => BuildHeadersTo (Header' mods h v ': xs ) where
109
109
buildHeadersTo headers = case L. find wantedHeader headers of
110
110
Nothing -> MissingHeader `HCons ` buildHeadersTo headers
111
111
Just header@ (_, val) -> case parseHeader val of
@@ -130,7 +130,7 @@ instance GetHeadersFromHList '[] where
130
130
getHeadersFromHList _ = []
131
131
132
132
instance (KnownSymbol h , ToHttpApiData x , GetHeadersFromHList xs )
133
- => GetHeadersFromHList (Header h x ': xs )
133
+ => GetHeadersFromHList (Header' mods h x ': xs )
134
134
where
135
135
getHeadersFromHList hdrs = case hdrs of
136
136
Header val `HCons ` rest -> (headerName , toHeader val) : getHeadersFromHList rest
@@ -151,42 +151,42 @@ instance GetHeaders' '[] where
151
151
getHeaders' _ = []
152
152
153
153
instance (KnownSymbol h , GetHeadersFromHList rest , ToHttpApiData v )
154
- => GetHeaders' (Header h v ': rest )
154
+ => GetHeaders' (Header' mods h v ': rest )
155
155
where
156
156
getHeaders' hs = getHeadersFromHList $ getHeadersHList hs
157
157
158
158
-- * Adding headers
159
159
160
160
-- We need all these fundeps to save type inference
161
- class AddHeader h v orig new
162
- | h v orig -> new , new -> h , new -> v , new -> orig where
161
+ class AddHeader ( mods :: [ * ]) h v orig new
162
+ | mods h v orig -> new , new -> mods , new -> h , new -> v , new -> orig where
163
163
addOptionalHeader :: ResponseHeader h v -> orig -> new -- ^ N.B.: The same header can't be added multiple times
164
164
165
165
-- In this instance, we add a Header on top of something that is already decorated with some headers
166
166
instance {-# OVERLAPPING #-} ( KnownSymbol h , ToHttpApiData v )
167
- => AddHeader h v (Headers (fst ': rest ) a ) (Headers (Header h v ': fst ': rest ) a ) where
167
+ => AddHeader mods h v (Headers (fst ': rest ) a ) (Headers (Header' mods h v ': fst ': rest ) a ) where
168
168
addOptionalHeader hdr (Headers resp heads) = Headers resp (HCons hdr heads)
169
169
170
170
-- In this instance, 'a' parameter is decorated with a Header.
171
- instance {-# OVERLAPPABLE #-} ( KnownSymbol h , ToHttpApiData v , new ~ Headers '[Header h v ] a )
172
- => AddHeader h v a new where
171
+ instance {-# OVERLAPPABLE #-} ( KnownSymbol h , ToHttpApiData v , new ~ Headers '[Header' mods h v ] a )
172
+ => AddHeader mods h v a new where
173
173
addOptionalHeader hdr resp = Headers resp (HCons hdr HNil )
174
174
175
175
-- Instances to decorate all responses in a 'Union' with headers. The functional
176
176
-- dependencies force us to consider singleton lists as the base case in the
177
177
-- recursion (it is impossible to determine h and v otherwise from old / new
178
178
-- responses if the list is empty).
179
- instance (AddHeader h v old new ) => AddHeader h v (Union '[old ]) (Union '[new ]) where
179
+ instance (AddHeader mods h v old new ) => AddHeader mods h v (Union '[old ]) (Union '[new ]) where
180
180
addOptionalHeader hdr resp =
181
181
SOP. Z $ SOP. I $ addOptionalHeader hdr $ SOP. unI $ SOP. unZ $ resp
182
182
183
183
instance
184
- ( AddHeader h v old new , AddHeader h v (Union oldrest ) (Union newrest )
184
+ ( AddHeader mods h v old new , AddHeader mods h v (Union oldrest ) (Union newrest )
185
185
-- This ensures that the remainder of the response list is _not_ empty
186
186
-- It is necessary to prevent the two instances for union types from
187
187
-- overlapping.
188
188
, oldrest ~ (a ': as ), newrest ~ (b ': bs ))
189
- => AddHeader h v (Union (old ': (a ': as ))) (Union (new ': (b ': bs ))) where
189
+ => AddHeader mods h v (Union (old ': (a ': as ))) (Union (new ': (b ': bs ))) where
190
190
addOptionalHeader hdr resp = case resp of
191
191
SOP. Z (SOP. I rHead) -> SOP. Z $ SOP. I $ addOptionalHeader hdr rHead
192
192
SOP. S rOthers -> SOP. S $ addOptionalHeader hdr rOthers
@@ -211,21 +211,21 @@ instance
211
211
-- Note that while in your handlers type annotations are not required, since
212
212
-- the type can be inferred from the API type, in other cases you may find
213
213
-- yourself needing to add annotations.
214
- addHeader :: AddHeader h v orig new => v -> orig -> new
214
+ addHeader :: AddHeader mods h v orig new => v -> orig -> new
215
215
addHeader = addOptionalHeader . Header
216
216
217
217
-- | Deliberately do not add a header to a value.
218
218
--
219
219
-- >>> let example1 = noHeader "hi" :: Headers '[Header "someheader" Int] String
220
220
-- >>> getHeaders example1
221
221
-- []
222
- noHeader :: AddHeader h v orig new => orig -> new
222
+ noHeader :: AddHeader mods h v orig new => orig -> new
223
223
noHeader = addOptionalHeader MissingHeader
224
224
225
225
class HasResponseHeader h a headers where
226
226
hlistLookupHeader :: HList headers -> ResponseHeader h a
227
227
228
- instance {-# OVERLAPPING #-} HasResponseHeader h a (Header h a ': rest ) where
228
+ instance {-# OVERLAPPING #-} HasResponseHeader h a (Header' mods h a ': rest ) where
229
229
hlistLookupHeader (HCons ha _) = ha
230
230
231
231
instance {-# OVERLAPPABLE #-} (HasResponseHeader h a rest ) => HasResponseHeader h a (first ': rest ) where
0 commit comments