F# 如何处理;选项“;温文尔雅的请求

F# 如何处理;选项“;温文尔雅的请求,f#,cors,elm,suave,F#,Cors,Elm,Suave,我正在移植一个原型应用程序,我使用elm和PythonFlask来使用elm和一个温和的后端。elm应用程序正在调用API从站点加载信息并执行其他操作。get请求似乎没有问题,但我在做elm的帖子时表现得很滑稽——对flask有效,但suave似乎不接受这个请求 抱歉,文章太长,详情如下: Elm代码: --POST IS WORKING TO Flask BUT NOT TO Suave testPassword editMode token = let data =

我正在移植一个原型应用程序,我使用elm和PythonFlask来使用elm和一个温和的后端。elm应用程序正在调用API从站点加载信息并执行其他操作。get请求似乎没有问题,但我在做elm的帖子时表现得很滑稽——对flask有效,但suave似乎不接受这个请求

抱歉,文章太长,详情如下:

Elm代码:

--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 flask,选项请求通过,响应表明需要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时,选项请求不完整或中断:

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
我的问题是,在温和的计划方面,我需要做些什么才能使这项工作正常进行? 我怀疑这是一种温和的配置,或者我需要编写一个Web部件来响应选项请求。代码如下:

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
让setCORSHeaders=
Console.WriteLine(“启用跨源请求”)
addHeader“访问控制允许来源”“*”
>=>setHeader“访问控制允许头”“令牌”
>=>addHeader“访问控制允许标题”“内容类型”
>=>addHeader“访问控制允许方法”“获取、选项、发布、放置”
让allowCors:Web部件=
选择[
获取>=>
趣味情境->
上下文|>(
塞特科谢德)
]
让应用程序=
..
州政府
>=>允许值
>=>选择
[获取>=>选择
[ //.. 
]
发布>=>选择
[//其他工作岗位
路径“/api/password/test”>=>上下文apiController.passwordTest
] 
选项>=>选择
[//也尝试过这个,但不认为它是正确的
路径“/api/password/test”>=>上下文apiController.passwordTest
] ]
让suaveCfg=
{defaultConfig with
serverKey=Convert.fromBase64字符串编码key
cookieSerialiser=新的JsonNetCookieSerialiser()
}
[]
让主argv=
startWebServer suaveCfg应用程序
0

感谢您阅读

我怀疑这是您的问题:

let allowCors : WebPart =
    choose [
        GET >=>
            fun context ->
                context |> (
                    setCORSHeaders )
    ]
这里没有
选项
案例,因此当通过应用程序发送选项请求时,
选择
组合器找不到与请求匹配的内容,因此返回
,这意味着处理链的其他部分永远不会被调用。在您的应用程序中,
allowCors
位于处理
选项的链的前面:

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 )
任何时候只要有
a->a |>otherFunction
,就可以用
otherFunction
替换该表达式。因此,您编写的
allowCors
函数如下所示:

let allowCors : WebPart =
    choose [
        GET >=>
            fun context ->
                context |> (
                    setCORSHeaders )
    ]
但它可能看起来像这样:

let allowCors : WebPart =
    choose [
        GET >=> setCORSHeaders
    ]

阅读起来容易多了,你不觉得吗?

非常感谢,已经按照建议进行了修改,请求正在通过-就在那里看着我:)-
让allowCors:WebPart=choose[GET>=>setCORSHeaders OPTIONS>=>setCORSHeaders POST>=>setCORSHeaders]
如果您的
allowCors
函数就是这样的,那么
choose
combinator是否有用?由于在管道中已经有一个
choose
,它将接受GET、POST或OPTIONS方法并拒绝所有其他方法,因此您可以只编写
let allowCors=setCORSHeaders
,它将具有相同的效果。或者,为了更加简单,
let-app=。。。statefulForSession>=>setCORSHeaders>=>选择[GET>=>…]