on master help sign in
Merge pull request #623 from haskell-servant/jkarni/noHeader

Add noHeader function.

commitc0906d1873b4e62ea2ac457a62343b13b511e47e authorJulian Arni <jkarni@gmail.com> dateMon 24 Oct 2016, 16:37 (10 years ago) parent3f6ecbb9ad2efe
4 files changed+50−6
servant/CHANGELOG.md+5 servant/src/Servant/API.hs+1−1 servant/src/Servant/API/ResponseHeaders.hs+38−5 servant/test/Servant/API/ResponseHeadersSpec.hs+6
servant/CHANGELOG.md+5
@@ -1,3 +1,8 @@
1+upcoming
2+--------
3+
4+* Added 'noHeader' function for *not* adding response headers.
5+
160.9
27---
38
servant/src/Servant/API.hs+1−1
@@ -75,7 +75,7 @@ import Servant.API.QueryParam (QueryFlag, QueryParam,
7575import Servant.API.Raw (Raw)
7676import Servant.API.RemoteHost (RemoteHost)
7777import Servant.API.ReqBody (ReqBody)
78−import Servant.API.ResponseHeaders (AddHeader (addHeader),
78+import Servant.API.ResponseHeaders (AddHeader, addHeader, noHeader,
7979 BuildHeadersTo (buildHeadersTo),
8080 GetHeaders (getHeaders),
8181 HList (..), Headers (..),
servant/src/Servant/API/ResponseHeaders.hs+38−5
@@ -23,7 +23,9 @@
2323-- example above).
2424module Servant.API.ResponseHeaders
2525 ( Headers(..)
26− , AddHeader(addHeader)
26+ , AddHeader
27+ , addHeader
28+ , noHeader
2729 , BuildHeadersTo(buildHeadersTo)
2830 , GetHeaders(getHeaders)
2931 , HeaderValMap
@@ -43,7 +45,7 @@ import Prelude ()
4345import Prelude.Compat
4446
4547-- | Response Header objects. You should never need to construct one directly.
46−-- Instead, use 'addHeader'.
48+-- Instead, use 'addOptionalHeader.
4749data Headers ls a = Headers { getResponse :: a
4850 -- ^ The underlying value of a 'Headers'
4951 , getHeadersHList :: HList ls
@@ -108,17 +110,48 @@ instance OVERLAPPABLE_ ( KnownSymbol h, GetHeaders (HList rest), ToHttpApiData v
108110-- We need all these fundeps to save type inference
109111class AddHeader h v orig new
110112 | h v orig -> new, new -> h, new -> v, new -> orig where
111− addHeader :: v -> orig -> new -- ^ N.B.: The same header can't be added multiple times
113+ addOptionalHeader :: Header h v -> orig -> new -- ^ N.B.: The same header can't be added multiple times
112114
113115
114116instance OVERLAPPING_ ( KnownSymbol h, ToHttpApiData v )
115117 => AddHeader h v (Headers (fst ': rest) a) (Headers (Header h v ': fst ': rest) a) where
116− addHeader a (Headers resp heads) = Headers resp (HCons (Header a) heads)
118+ addOptionalHeader hdr (Headers resp heads) = Headers resp (HCons hdr heads)
117119
118120instance OVERLAPPABLE_ ( KnownSymbol h, ToHttpApiData v
119121 , new ~ (Headers '[Header h v] a) )
120122 => AddHeader h v a new where
121− addHeader a resp = Headers resp (HCons (Header a) HNil)
123+ addOptionalHeader hdr resp = Headers resp (HCons hdr HNil)
124+
125+-- | @addHeader@ adds a header to a response. Note that it changes the type of
126+-- the value in the following ways:
127+--
128+-- 1. A simple value is wrapped in "Headers [<hdr>]":
129+--
130+-- >>> let example1 = addHeader 5 "hi" :: Headers '[Header "someheader" Int] String;
131+-- >>> getHeaders example1
132+-- [("someheader","5")]
133+--
134+-- 2. A value that already has a header has its new header *prepended* to the
135+-- existing list:
136+--
137+-- >>> let example1 = addHeader 5 "hi" :: Headers '[Header "someheader" Int] String;
138+-- >>> let example2 = addHeader True example1 :: Headers '[Header "1st" Bool, Header "someheader" Int] String
139+-- >>> getHeaders example2
140+-- [("1st","true"),("someheader","5")]
141+--
142+-- Note that while in your handlers type annotations are not required, since
143+-- the type can be inferred from the API type, in other cases you may find
144+-- yourself needing to add annotations.
145+addHeader :: AddHeader h v orig new => v -> orig -> new
146+addHeader = addOptionalHeader . Header
147+
148+-- | Deliberately do not add a header to a value.
149+--
150+-- >>> let example1 = noHeader "hi" :: Headers '[Header "someheader" Int] String
151+-- >>> getHeaders example1
152+-- []
153+noHeader :: AddHeader h v orig new => orig -> new
154+noHeader = addOptionalHeader MissingHeader
122155
123156-- $setup
124157-- >>> import Servant.API
servant/test/Servant/API/ResponseHeadersSpec.hs+6
@@ -22,3 +22,9 @@ spec = describe "Servant.API.ResponseHeaders" $ do
2222 it "adds headers to the front of the list" $ do
2323 let val = addHeader 10 $ addHeader "b" 5 :: Headers '[Header "first" Int, Header "second" String] Int
2424 getHeaders val `shouldBe` [("first", "10"), ("second", "b")]
25+
26+ describe "noHeader" $ do
27+
28+ it "does not add a header" $ do
29+ let val = noHeader 5 :: Headers '[Header "test" Int] Int
30+ getHeaders val `shouldBe` []