如何在 suave 中处理 "OPTIONS" 请求
How to handle "OPTIONS" requests in suave
我正在移植一个原型应用程序,我使用 elm 和 python flask 来使用 elm 和 suave 后端。 elm 应用程序正在调用 API 从网站加载信息并做一些其他事情。 get 请求似乎没有问题,但是当我从 elm 执行 POST 时,我的行为很有趣 - 适用于 flask,但 suave 似乎不接受该请求。
很抱歉post,详情如下:
榆木代码:
--POST IS WORKING TO Flask BUT NOT TO Suave
testPassword editMode token =
let
data =
Json.Encode.object
[ ( "email", Json.Encode.string editMode.email )
, ( "password", Json.Encode.string editMode.newValue )
]
body =
Json.Encode.object [ ("data", data) ]
decodeVal value =
Json.Decode.map2 RestResponse
(field "success" Json.Decode.bool)
(field "errorMessage" Json.Decode.string)
valDecoder =
Json.Decode.value
|> Json.Decode.andThen decodeVal
postTo =
String.concat [ apiUrl, token, "/api/password/test" ]
in
Json.Decode.field "data" valDecoder
|> Http.post (postTo) (jsonBody body)
|> Http.send UpdateValue
在 chrome 中调试 我可以看到 python 烧瓶的 OPTIONS 请求通过并且响应表明需要 POST
General
Request URL: http://localhost:5000/api/password/test
Request Method: OPTIONS
Status Code: 200 OK
Remote Address: 127.0.0.1:5000
Referrer Policy: no-referrer-when-downgrade
Response Headers
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: *
Allow: OPTIONS, POST
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Wed, 30 May 2018 09:35:08 GMT
Server: Werkzeug/0.14.1 Python/3.5.2
但是,对于 Suave,OPTIONS 请求不完整或中断:
General
Request URL: http://localhost:8080/api/password/test
Referrer Policy: no-referrer-when-downgrade
Request Headers
Provisional headers are shown
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
我的问题是我需要在 suave 程序方面做什么才能让它工作?
我怀疑它要么是温和的配置,要么我需要编写 WebPart 代码来响应选项请求。代码如下:
let setCORSHeaders =
Console.WriteLine("Enabling cross origin requests")
addHeader "Access-Control-Allow-Origin" "*"
>=> setHeader "Access-Control-Allow-Headers" "token"
>=> addHeader "Access-Control-Allow-Headers" "content-type"
>=> addHeader "Access-Control-Allow-Methods" "GET,OPTIONS,POST,PUT"
let allowCors : WebPart =
choose [
GET >=>
fun context ->
context |> (
setCORSHeaders )
]
let app =
..
statefulForSession
>=> allowCors
>=> choose
[ GET >=> choose
[ //..
]
POST >=> choose
[ //other posts working
path "/api/password/test" >=> context apiController.passwordTest
]
OPTIONS >=> choose
[ //tried this as well but don't think it's correct
path "/api/password/test" >=> context apiController.passwordTest
] ]
let suaveCfg =
{ defaultConfig with
serverKey = Convert.FromBase64String encodedkey
cookieSerialiser = new JsonNetCookieSerialiser()
}
[<EntryPoint>]
let main argv =
startWebServer suaveCfg app
0
感谢阅读
我怀疑这是你的问题:
let allowCors : WebPart =
choose [
GET >=>
fun context ->
context |> (
setCORSHeaders )
]
此处没有 OPTIONS
情况,因此当 OPTIONS 请求通过您的应用时,choose
组合器找不到与请求匹配的任何内容,因此 returns None
,这意味着永远不会调用处理链的其他部分。在您的应用程序中,allowCors
出现在链中处理 OPTIONS
:
的部分之前
let app =
..
statefulForSession
>=> allowCors
>=> choose
[ GET >=> choose
[ //..
]
// Elided the POST part here
OPTIONS >=> choose
[ //tried this as well but don't think it's correct
path "/api/password/test" >=> context apiController.passwordTest
] ]
在您的 allowCors
WebPart 中放置一个 OPTIONS
部分,我认为您的代码应该可以工作。
编辑: 此外,allowCors
中的这段代码可以改进:
fun context ->
context |> (
setCORSHeaders )
任何时候你有 fun a -> a |> otherFunction
,你可以用 otherFunction
替换那个表达式。所以你的 allowCors
函数,如所写,看起来像这样:
let allowCors : WebPart =
choose [
GET >=>
fun context ->
context |> (
setCORSHeaders )
]
但它可能看起来像这样:
let allowCors : WebPart =
choose [
GET >=> setCORSHeaders
]
更容易阅读,你不觉得吗?
我正在移植一个原型应用程序,我使用 elm 和 python flask 来使用 elm 和 suave 后端。 elm 应用程序正在调用 API 从网站加载信息并做一些其他事情。 get 请求似乎没有问题,但是当我从 elm 执行 POST 时,我的行为很有趣 - 适用于 flask,但 suave 似乎不接受该请求。
很抱歉post,详情如下:
榆木代码:
--POST IS WORKING TO Flask BUT NOT TO Suave
testPassword editMode token =
let
data =
Json.Encode.object
[ ( "email", Json.Encode.string editMode.email )
, ( "password", Json.Encode.string editMode.newValue )
]
body =
Json.Encode.object [ ("data", data) ]
decodeVal value =
Json.Decode.map2 RestResponse
(field "success" Json.Decode.bool)
(field "errorMessage" Json.Decode.string)
valDecoder =
Json.Decode.value
|> Json.Decode.andThen decodeVal
postTo =
String.concat [ apiUrl, token, "/api/password/test" ]
in
Json.Decode.field "data" valDecoder
|> Http.post (postTo) (jsonBody body)
|> Http.send UpdateValue
在 chrome 中调试 我可以看到 python 烧瓶的 OPTIONS 请求通过并且响应表明需要 POST
General
Request URL: http://localhost:5000/api/password/test
Request Method: OPTIONS
Status Code: 200 OK
Remote Address: 127.0.0.1:5000
Referrer Policy: no-referrer-when-downgrade
Response Headers
Access-Control-Allow-Headers: *
Access-Control-Allow-Origin: *
Allow: OPTIONS, POST
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Wed, 30 May 2018 09:35:08 GMT
Server: Werkzeug/0.14.1 Python/3.5.2
但是,对于 Suave,OPTIONS 请求不完整或中断:
General
Request URL: http://localhost:8080/api/password/test
Referrer Policy: no-referrer-when-downgrade
Request Headers
Provisional headers are shown
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
我的问题是我需要在 suave 程序方面做什么才能让它工作? 我怀疑它要么是温和的配置,要么我需要编写 WebPart 代码来响应选项请求。代码如下:
let setCORSHeaders =
Console.WriteLine("Enabling cross origin requests")
addHeader "Access-Control-Allow-Origin" "*"
>=> setHeader "Access-Control-Allow-Headers" "token"
>=> addHeader "Access-Control-Allow-Headers" "content-type"
>=> addHeader "Access-Control-Allow-Methods" "GET,OPTIONS,POST,PUT"
let allowCors : WebPart =
choose [
GET >=>
fun context ->
context |> (
setCORSHeaders )
]
let app =
..
statefulForSession
>=> allowCors
>=> choose
[ GET >=> choose
[ //..
]
POST >=> choose
[ //other posts working
path "/api/password/test" >=> context apiController.passwordTest
]
OPTIONS >=> choose
[ //tried this as well but don't think it's correct
path "/api/password/test" >=> context apiController.passwordTest
] ]
let suaveCfg =
{ defaultConfig with
serverKey = Convert.FromBase64String encodedkey
cookieSerialiser = new JsonNetCookieSerialiser()
}
[<EntryPoint>]
let main argv =
startWebServer suaveCfg app
0
感谢阅读
我怀疑这是你的问题:
let allowCors : WebPart =
choose [
GET >=>
fun context ->
context |> (
setCORSHeaders )
]
此处没有 OPTIONS
情况,因此当 OPTIONS 请求通过您的应用时,choose
组合器找不到与请求匹配的任何内容,因此 returns None
,这意味着永远不会调用处理链的其他部分。在您的应用程序中,allowCors
出现在链中处理 OPTIONS
:
let app =
..
statefulForSession
>=> allowCors
>=> choose
[ GET >=> choose
[ //..
]
// Elided the POST part here
OPTIONS >=> choose
[ //tried this as well but don't think it's correct
path "/api/password/test" >=> context apiController.passwordTest
] ]
在您的 allowCors
WebPart 中放置一个 OPTIONS
部分,我认为您的代码应该可以工作。
编辑: 此外,allowCors
中的这段代码可以改进:
fun context ->
context |> (
setCORSHeaders )
任何时候你有 fun a -> a |> otherFunction
,你可以用 otherFunction
替换那个表达式。所以你的 allowCors
函数,如所写,看起来像这样:
let allowCors : WebPart =
choose [
GET >=>
fun context ->
context |> (
setCORSHeaders )
]
但它可能看起来像这样:
let allowCors : WebPart =
choose [
GET >=> setCORSHeaders
]
更容易阅读,你不觉得吗?