【问题标题】:Haskell Yesod - CORS problems with browsers OPTIONS requests when doing POST requestsHaskell Yesod - 执行 POST 请求时浏览器 OPTIONS 请求的 CORS 问题
【发布时间】:2017-05-14 22:06:28
【问题描述】:

我使用了Network.Wai.Middleware.CorssimpleCors,它可以正常处理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 处理程序!非常感谢任何帮助!

【问题讨论】:

    标签: rest haskell request cors yesod


    【解决方案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"
    

    【讨论】:

      猜你喜欢
      • 2019-08-29
      • 2018-11-19
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 2015-03-09
      • 2015-03-01
      • 2020-12-20
      • 2016-06-28
      相关资源
      最近更新 更多