2014-11-01 75 views
3

我想通过编写一个非常简单的会话管理器来了解中间件。在Haskell WAI中,如何添加标题作为中间件?

我需要在响应中添加SetCookie标头。我看了一下wai-extra包,发现wai-session

我正在使用wai-3.0.2,它似乎没有给我直接访问响应的类型构造函数,并且我发现在Response(..)上找到模式匹配以添加标题的所有示例。

您能否指点我正确的方向?

+1

你当然可以导入'Network.Wai.Internal'来模式匹配'Response'的构造函数。 – ibotty 2014-11-01 21:06:10

+0

@ibotty好吧,我感到很傻。我试过了,但失败了。结果失败了,因为其中一个类型构造函数的名称已经改变,我没有注意到。 – rob 2014-11-02 01:29:18

+0

下一次尝试在ghci中探索它。使用':i',你将会了解所有的构造函数以及它们的定义。 – ibotty 2014-11-03 09:19:10

回答

5

编辑:Wai版本3.0.3.0引入了一个辅助函数mapResponseHeaders,与以下示例中的mapHeader相同。这意味着该示例不再需要在Response上进行模式匹配。

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) 

我有什么工作,并认为我的理解,但会真的喜欢的反馈和建议。我是Haskell的新手,这是我第一次使用Wai。我最大的绊脚石是没有意识到应用程序类型在Wai 3.0.0中更改为延续传递样式。 (该文件指出这非常清楚,我只是错过了它的第15次我读了它。)

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 _ [email protected](ResponseRaw _ _) = r 

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

我没有试图修改标题为ResponseRaw,因为我无法弄清楚如何。

我不确定这是否足够清楚,addHeader部分应用,并且是传递给内部应用程序的延续功能。这种形式可能是更清晰的(或丑陋):

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

我从wai-session复制mapHeader,但添加的情况下ResponseRaw。

+0

不幸的是必须从Network.Wai.Internal中导入Response构造函数,但据我所知,这是您完成它的唯一方法。 – hdgarrood 2015-07-03 07:33:28

+0

另外,部分应用的addHeader对我来说很清楚;我宁愿比那个eta扩展版本。最后,在mapHeader的最后一个模式中,由于未使用“f”,我宁愿将'_'用于'f'。 (我认为如果你使用了-Wall,这会产生一个警告) – hdgarrood 2015-07-03 07:35:58

+0

@hdgarrood我把未使用的'f'改成'_'。那更好。随着我对Haskell习以为常,我更喜欢部分应用的版本。感谢您的评论! – rob 2015-07-03 19:46:34

相关问题