Haskell Yesod - 执行 POST 请求时浏览器 OPTIONS 请求的 CORS 问题
Posted
技术标签:
【中文标题】Haskell Yesod - 执行 POST 请求时浏览器 OPTIONS 请求的 CORS 问题【英文标题】:Haskell Yesod - CORS problems with browsers OPTIONS requests when doing POST requests 【发布时间】:2017-05-14 22:06:28 【问题描述】:我使用了Network.Wai.Middleware.Cors
的simpleCors
,它可以正常处理GET
请求,但是当我尝试发出POST
请求时,我遇到了以下问题
OPTIONS /users
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Status: 400 Bad Request 0.032443s
我能够使它工作的唯一方法是从Application.hs
的以下部分中删除simpleCors
-- | Convert our foundation to a WAI Application by calling @toWaiAppPlain@ and
-- applying some additional middlewares.
makeApplication :: App -> IO Application
makeApplication foundation = do
logWare <- makeLogWare foundation
-- Create the WAI application and apply middlewares
appPlain <- toWaiAppPlain foundation
return $ logWare $ defaultMiddlewaresNoLogging $ simpleCors $ appPlain
并添加一个 OPTIONS 方法响应
optionsNewUserR :: Handler RepPlain
optionsNewUserR = do
return $ RepPlain $ toContent ("" :: Text)
并添加 CORS 标头...但这是一个肮脏的解决方案,因为我需要更改所有 API 处理程序!非常感谢任何帮助!
【问题讨论】:
【参考方案1】:我认为问题在于 simpleCors 是基于 simpleCorsResourcePolicy 构建的,后者仅涵盖 simpleMethods,不涵盖 OPTIONS
。
您可以通过使用相同的方法来滚动您需要的任何中间件来解决此问题。
这是我用于解决您描述的OPTIONS
问题的方法:
-# LANGUAGE OverloadedStrings #-
module Middlewares where
import Network.Wai (Middleware)
import Network.Wai.Middleware.AddHeaders (addHeaders)
import Network.Wai.Middleware.Cors (CorsResourcePolicy(..), cors)
-- | @x-csrf-token@ allowance.
-- The following header will be set: @Access-Control-Allow-Headers: x-csrf-token@.
allowCsrf :: Middleware
allowCsrf = addHeaders [("Access-Control-Allow-Headers", "x-csrf-token,authorization")]
-- | CORS middleware configured with 'appCorsResourcePolicy'.
corsified :: Middleware
corsified = cors (const $ Just appCorsResourcePolicy)
-- | Cors resource policy to be used with 'corsified' middleware.
--
-- This policy will set the following:
--
-- * RequestHeaders: @Content-Type@
-- * MethodsAllowed: @OPTIONS, GET, PUT, POST@
appCorsResourcePolicy :: CorsResourcePolicy
appCorsResourcePolicy = CorsResourcePolicy
corsOrigins = Nothing
, corsMethods = ["OPTIONS", "GET", "PUT", "POST"]
, corsRequestHeaders = ["Authorization", "Content-Type"]
, corsExposedHeaders = Nothing
, corsMaxAge = Nothing
, corsVaryOrigin = False
, corsRequireOrigin = False
, corsIgnoreFailures = False
然后就像你已经在做的那样编写你需要的中间件:
run port $ logger . allowCsrf . corsified $ app cfg
【讨论】:
实际上我是在正确的道路上,我做了同样的事情,通过与 simpleCors 实现进行比较,但我使用corsRequestHeaders = []
而不是 corsRequestHeaders = ["Authorization", "Content-Type"]
。这部分有什么作用?另一件事,你用什么 IDE/Editor 在 Haskell 中编码 :) ?
另一件事,我必须添加import Prelude
文档是你的朋友!查看hackage.haskell.org/package/wai-cors-0.2.5/docs/src/… 您的项目可能必须在全球范围内排除 Prelude 吗?我只使用 Sublime Text 或 Vim,但这些可能是更一般的问题,适合非问题讨论!【参考方案2】:
简化马里奥的答案,我们可以使用 simplePolicy
import Network.Wai.Middleware.Cors
allowCors :: Middleware
allowCors = cors (const $ Just appCorsResourcePolicy)
appCorsResourcePolicy :: CorsResourcePolicy
appCorsResourcePolicy =
simpleCorsResourcePolicy
corsMethods = ["OPTIONS", "GET", "PUT", "POST"]
, corsRequestHeaders = ["Authorization", "Content-Type"]
并使用它:
main = scotty 8080 $ do
middleware allowCors
matchAny "/" $ text "Success"
【讨论】:
以上是关于Haskell Yesod - 执行 POST 请求时浏览器 OPTIONS 请求的 CORS 问题的主要内容,如果未能解决你的问题,请参考以下文章
当用户不在 Yesod/Haskell 的数据库中时如何重定向到特殊页面
Haskell,Yesod和Keter - 我如何定期(每5分钟)运行一次例行程序?