In Haskell WAI, how do I add headers as middleware?

I am trying to understand Middleware by writing a very simple session manager.

I need to add a header SetCookie

in the response. I went through the package wai-extra

and found wai-session

.

I'm using wai-3.0.2, which doesn't seem to give me direct access to constructors like Response, and all the examples I've found follow the pattern Response(..)

for adding headers.

Can you point me in the right direction?

+3


source to share


1 answer


Edit: Version 3.0.3.0 of Wai introduces a helper function mapResponseHeaders

which is the same as mapHeader

in the example below. This means that the example Response

no longer needs to match patterns.

import Network.HTTP.Types (ResponseHeaders, Header)
import Network.Wai (Middleware, Response, mapResponseHeaders)

withHeader :: Header -> Middleware
withHeader h app req respond = app req $ respond . addHeader h

addHeader :: Header -> Response -> Response
addHeader h = mapResponseHeaders (\hs -> h:hs)

      


Something is working for me, and I think I understand it, but I would really like the feedback and suggestions. I am new to Haskell and this is my first use of Wai. My biggest stumbling block was not realizing that the app type changed in Wai 3.0.0 to the continuation style. (The documentation says it very clearly , I just skipped it the first 15 times I read it.)

import Network.HTTP.Types (ResponseHeaders, Header)
import Network.Wai (Middleware)
import Network.Wai.Internal (Response(..))

withHeader :: Header -> Middleware
withHeader h app req respond = app req $ respond . addHeader h

mapHeader :: (ResponseHeaders -> ResponseHeaders) -> Response -> Response
mapHeader f (ResponseFile s h b1 b2) = ResponseFile s (f h) b1 b2
mapHeader f (ResponseBuilder s h b) = ResponseBuilder s (f h) b
mapHeader f (ResponseStream s h b) = ResponseStream s (f h) b
mapHeader _ r@(ResponseRaw _ _) = r

addHeader :: Header -> Response -> Response
addHeader h = mapHeader (\hs -> h:hs)

      



I didn't try to change the headers for ResponseRaw

because I couldn't figure out how to do it.

I'm not sure if it's clear enough what addHeader

partially applies and is the continuation function passed into the internal application. This form might be clearer (or uglier):

withHeader h app req respond = app req $ \resp -> respond $ addHeader h resp

      

I copied mapHeader

from wai-session but added a case for ResponseRaw.

+5


source







All Articles