CORS 预检神秘地失败 gorilla/handlers
CORS preflight mysteriously failing with gorilla/handlers
我正在通过 Heroku 为我的应用程序发布一个 Golang API。无法让我的 webapp(Flutter/Dart 堆栈)实际从我的 api 获得成功响应。但是我 am 能够使用来自本地的 curl 命令获得成功的响应。我已经阅读了几篇关于更改 Go mux 服务器并添加正确的 headers 的文章,但这对我没有用。我什至看到这些 headers 在我的 curl 请求期间返回。真的需要一些帮助,因为这让我慢下来了。
基本上这是我的主要 class 创建服务器
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\n", 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);
我在 2 个单独的 Heroku Dynos 中托管 Web 应用程序和 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
我以为我应该看到那里添加了 Header Access-Control-Allow-Origin: *
,但现在还没有,我仍然获得了 200 次成功。但是,当我尝试使用我的 Webapp 使用 Google Chrome 从登录屏幕点击 API 时,我看到了这个错误:
Access to XMLHttpRequest at 'https://my-app-api.herokuapp.com/api/login' from origin 'https://my-app-staging.herokuapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
不知道 - header 好像被 Chrome 或其他什么东西删除了?
编辑:我也尝试使用 CURL 发送预检请求,我看到了正确的 headers - 但是它仍然显示 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
的通配符。您必须明确指定所有允许的 header。在你的情况下,而不是
handlers.AllowedHeaders([]string{"*"})
你应该
handlers.AllowedHeaders([]string{"content-type", "username", "password"})
更多详情
Fetch standard added support (in the case of non-credentialed requests) for the wildcard in the Access-Control-Allow-Headers
header back in 2016. Most modern browsers now support this feature.
但是,gorilla/handlers 似乎还没有赶上规范。如果您检查 handlers.AllowedHeaders
函数 和 *cors.ServeHTTP
方法 的源代码,您会发现"*"
值没有特殊处理:按字面意思处理。因此,CORS 中间件 检测到您的预检请求(content-type
、username
和 password
) 和您允许的 headers(*
,从字面上看)和 以 403
响应,甚至没有设置 Access-Control-Allow-Origin
header,从而导致 access-control 检查失败。
我正在通过 Heroku 为我的应用程序发布一个 Golang API。无法让我的 webapp(Flutter/Dart 堆栈)实际从我的 api 获得成功响应。但是我 am 能够使用来自本地的 curl 命令获得成功的响应。我已经阅读了几篇关于更改 Go mux 服务器并添加正确的 headers 的文章,但这对我没有用。我什至看到这些 headers 在我的 curl 请求期间返回。真的需要一些帮助,因为这让我慢下来了。
基本上这是我的主要 class 创建服务器
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\n", 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);
我在 2 个单独的 Heroku Dynos 中托管 Web 应用程序和 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
我以为我应该看到那里添加了 Header Access-Control-Allow-Origin: *
,但现在还没有,我仍然获得了 200 次成功。但是,当我尝试使用我的 Webapp 使用 Google Chrome 从登录屏幕点击 API 时,我看到了这个错误:
Access to XMLHttpRequest at 'https://my-app-api.herokuapp.com/api/login' from origin 'https://my-app-staging.herokuapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
不知道 - header 好像被 Chrome 或其他什么东西删除了?
编辑:我也尝试使用 CURL 发送预检请求,我看到了正确的 headers - 但是它仍然显示 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
的通配符。您必须明确指定所有允许的 header。在你的情况下,而不是
handlers.AllowedHeaders([]string{"*"})
你应该
handlers.AllowedHeaders([]string{"content-type", "username", "password"})
更多详情
Fetch standard added support (in the case of non-credentialed requests) for the wildcard in the Access-Control-Allow-Headers
header back in 2016. Most modern browsers now support this feature.
但是,gorilla/handlers 似乎还没有赶上规范。如果您检查 handlers.AllowedHeaders
函数 和 *cors.ServeHTTP
方法 的源代码,您会发现"*"
值没有特殊处理:按字面意思处理。因此,CORS 中间件 检测到您的预检请求(content-type
、username
和 password
) 和您允许的 headers(*
,从字面上看)和 以 403
响应,甚至没有设置 Access-Control-Allow-Origin
header,从而导致 access-control 检查失败。