CORS飞行前神秘地与大猩猩/训练员失败 [英] CORS preflight mysteriously failing with gorilla/handlers

查看:18
本文介绍了CORS飞行前神秘地与大猩猩/训练员失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过Heroku为我的应用程序发布了一个Golang API。不能让我的网络应用程序(扑翼/飞镖堆栈)真正从我的API中获得成功的响应。但是,我能够从本地使用cURL命令获得成功的响应。我已经阅读了几篇关于更改GO多路复用器服务器和添加正确的头的帖子,但这对我来说并不起作用。我甚至看到这些头在我的cURL请求期间返回。我真的需要一些帮助,因为这让我慢了下来。

基本上这是我创建服务器的主类

import (
    "api/preventative_care"
    "api/user"
    "github.com/gorilla/handlers"
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "os"
)

func main() {
    log.SetFlags(log.LstdFlags | log.Llongfile)
    router := mux.NewRouter()

    // Where ORIGIN_ALLOWED is like `scheme://dns[:port]`, or `*` (insecure)

    headersOk := handlers.AllowedHeaders([]string{"*"})
    methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
    originsOk := handlers.AllowedOrigins([]string{"*"})

    router.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
        log.Println("Up and running!")
    })
    router.HandleFunc("/api/login", user.LoginHandler).Methods("GET")
    router.HandleFunc("/api/recommendations", preventative_care.RecommendationHandler).Methods("GET")

    var port = os.Getenv("PORT")
    log.Printf("Starting application on port %s
", port)

    //log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), router))
    log.Fatal(http.ListenAndServe(":" + os.Getenv("PORT"), handlers.CORS(originsOk, headersOk, methodsOk)(router)))

}

调用此API的DART代码如下:

    Map<String, String> headers = {
      "content-type": "application/json",
      "username": username,
      "password": password
    };

    final response = await http.get(Uri.parse(uri), headers: headers);

我在两个独立的Heroku dynos中托管WebApp和API。当我在本地使用curl点击API时,我看到以下内容:

$ > curl -iXGET https://my-app-api.herokuapp.com/api/login -H "username:hello" -H "password:pizza"

HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
Content-Type: application/json
Date: Thu, 18 Nov 2021 23:39:56 GMT
Content-Length: 160
Via: 1.1 vegur

我以为我应该看到标题Access-Control-Allow-Origin: *添加在那里,但还没有成功返回200。但是,当我尝试使用我的Web应用程序从使用Google Chrome的登录屏幕访问API时,我看到以下错误:

CORS策略已阻止在‘https://my-app-api.herokuapp.com/api/login’From Origin‘https://my-app-staging.herokuapp.com’访问XMLHttpRequest.对印前检查请求的响应未通过访问控制检查:请求的资源上不存在‘Access-Control-Allow-Origin’标头。

不知道-好像标题被Chrome或其他什么东西删除了?

编辑:我还尝试使用cURL发送印前检查请求,我看到了正确的标题,但仍显示4xx错误。

$ > curl -H "Access-Control-Request-Method: GET" -H "Origin: https://my-app-staging.herokuapp.com" --head https://my-app-api.herokuapp.com/api/login

HTTP/1.1 405 Method Not Allowed
Server: Cowboy
Connection: keep-alive
Access-Control-Allow-Origin: *
Date: Fri, 19 Nov 2021 00:51:52 GMT
Via: 1.1 vegur

所以现在我真的不确定

推荐答案

TL;DR

gorilla/handlers(还没有?)支持Access-Control-Allow-Headers的通配符。您必须显式指定所有允许的标头。在您的情况下,而不是

handlers.AllowedHeaders([]string{"*"})

您应该有

handlers.AllowedHeaders([]string{"content-type", "username", "password"})

详细信息

Fetch standardAccess-Control-Allow-Headersback in 2016中添加了对通配符的支持(在无凭据请求的情况下)。大多数现代浏览器现在support this feature

然而,gorilla/handlers似乎还没有赶上规范。如果检查the handlers.AllowedHeaders functionthe *cors.ServeHTTP method的源代码,您会发现"*"值没有特殊处理:它是逐字处理的。因此,在您的印前检查请求提供的请求头(content-typeusernamepassword)和您允许的头(*)和responds with a 403之间的CORS中间件detects a mismatch甚至没有设置Access-Control-Allow-Origin头,从而导致访问控制检查失败。

这篇关于CORS飞行前神秘地与大猩猩/训练员失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆