在Yesod中允许跨源请求

时间:2013-04-02 21:33:38

标签: ajax haskell bookmarklet cors yesod

我的应用程序使用bookmarklet,我需要允许MyRouteR的CORS,所以我的bookmarklet代码可以使用此路由进行AJAX请求。

在我的配置/路由初稿中,我只对一个请求方法PUT提供MyRouteR支持。但事实证明,我也需要支持OPTIONS方法,这些浏览器用于CORS预检请求。

我在config / routes中得到了以下结果:

/myroute MyRouteR PUT OPTIONS

我有点希望在模板Haskell中有一些相关的机制来处理配置/路由,以便在这个路由的方法列表中添加OPTIONS会自动导致CORS支持,但没有骰子。不是世界的尽头,但它会有意义并且感觉很优雅。

为了使CORS正常工作,我给路由一个OPTIONS处理程序:

optionsMyRouteR :: Handler RepPlain
optionsMyRouteR = do
    addHeader "Access-Control-Allow-Origin" "*"
    addHeader "Access-Control-Allow-Methods" "PUT, OPTIONS"
    return $ RepPlain $ toContent ("" :: Text)

putMyRouteR :: Handler RepJson
putMyRouteR = do
    addHeader "Access-Control-Allow-Origin" "*"
    -- more stuff ...

这是有效的,但感觉有点不太正常,因为它是如此的样板。所以,有两个问题:

  1. 我们有比Yesodic更好的形容词吗?
  2. 还有另一种更好的方法让路由支持跨源请求吗?

1 个答案:

答案 0 :(得分:3)

<强>更新 其他人为此发布了一些通用中间件:http://hackage.haskell.org/package/wai-cors


我目前正在开展相同的工作并且还没有实现解决方案,但是我想它可以通过类似于wiki页面Allowing WOFF fonts to be accessed from other domains (CORS)上的示例代码的WAI Middleware来完成。这应该允许您编写一次CORS代码而无需重复自己。

上面链接中的示例代码,用于添加WOFF字体的跨域访问:

addCORStoWOFF :: W.Middleware
addCORStoWOFF app = fmap updateHeaders . app
  where
    updateHeaders (W.ResponseFile    status headers fp mpart) = W.ResponseFile    status (new headers) fp mpart
    updateHeaders (W.ResponseBuilder status headers builder)  = W.ResponseBuilder status (new headers) builder
    updateHeaders (W.ResponseSource  status headers src)      = W.ResponseSource  status (new headers) src
    new headers | woff      = cors : headers
                | otherwise =        headers
      where woff = lookup HT.hContentType headers == Just "application/font-woff"
            cors = ("Access-Control-Allow-Origin", "*")