Joh*_*ohn 5 javascript go cors
我有一个我不明白的错误,如果我在Golang上做错了,或者我在使用javascript fetch()语句做错了.这是一个简单的情况,我想fetch()调用golang端点并简单地打印hello world.但出于某种原因,golang代码会发射两次.这是我的代码:
// main.go
package main
import (
"route/page"
"github.com/gorilla/mux"
"log"
"net/http"
)
func main() {
router := mux.NewRouter()
router.HandleFunc("/page", page.Search).Methods("GET","OPTIONS")
log.Fatal(http.ListenAndServe(":8000", router))
}
//route/page.go
package page
import (
"net/http"
"log"
)
func Search(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, Authorization, Organization")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")
log.Println(r.Header.Get("authorization"))
log.Println("Hello World")
w.Write([]byte("{}"))
return
}
Run Code Online (Sandbox Code Playgroud)
然后我去了JSFiddle.net并粘贴了以下JS代码并按下Run:
fetch('http://192.168.0.21:8000/page', {
method: 'GET',
headers: {
'Content-Type': 'text/plain',
'Organization': 'afae3@@@@@%2Fajfoij',
'Authorization': 'Basic tajoie#$@asdfall%DF;++JI%2F3255',
}
})
Run Code Online (Sandbox Code Playgroud)
由于某种原因,我的控制台两次打印Hello World:
john@ubuntu:~/go/src/myproject$ go run main.go
2018/09/20 18:42:29
2018/09/20 18:42:29 Hello World
2018/09/20 18:42:29 Basic tajoie#$@asdfall%DF;++JI%2F3255
2018/09/20 18:42:29 Hello World
Run Code Online (Sandbox Code Playgroud)
我将我的JS代码转换为PHP,将我的PHP代码放在与golang代码相同的localhost上,从控制台运行PHP代码,并获得仅执行ONCE的golang代码的预期结果.有谁知道发生了什么?我误解了一些事情fetch()吗?我设置标题的方式是否有不寻常的事情发生?
小智 8
router.HandleFunc("/page", page.Search).Methods("GET","OPTIONS")
Run Code Online (Sandbox Code Playgroud)
告诉路由器直接既 GET和OPTIONS方法来搜索处理程序.
CORS预检通常由单独的处理程序处理.在您的情况下,您告诉Go使用搜索处理程序处理飞行前检查和获取请求.
通常,您希望与后续请求分开处理飞行前检查,因此请求未执行两次(一次无理由).
一个非常简单的飞行前处理程序版本将是:
func PreFlightHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "http://localhost")
w.Header().Set("Vary", "Origin")
w.Header().Set("Vary", "Access-Control-Request-Method")
w.Header().Set("Vary", "Access-Control-Request-Headers")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Origin, Accept")
w.Header().Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
w.Header().Set("Access-Control-Allow-Credentials", "true")
}
Run Code Online (Sandbox Code Playgroud)
完整的Golang代码将是:
// main.go
package main
import (
"route/page"
"github.com/gorilla/mux"
"log"
"net/http"
)
func main() {
router := mux.NewRouter()
router.HandleFunc("/page", page.PreFlightHandler).Methods("OPTIONS")
router.HandleFunc("/page", page.Search).Methods("GET")
log.Fatal(http.ListenAndServe(":8000", router))
}
// route/page.go
package page
import (
"net/http"
"log"
)
func PreFlightHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Vary", "Origin")
w.Header().Set("Vary", "Access-Control-Request-Method")
w.Header().Set("Vary", "Access-Control-Request-Headers")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Origin, Accept, Authorization, Organization")
w.Header().Set("Access-Control-Allow-Methods", "GET,POST,OPTIONS")
w.Header().Set("Access-Control-Allow-Credentials", "true")
}
func Search(w http.ResponseWriter, r *http.Request) {
log.Println(r.Header.Get("authorization"))
log.Println("Hello World")
w.Write([]byte("{}"))
return
}
Run Code Online (Sandbox Code Playgroud)
这是spencedev的扩展答案
作为用户rmn用户所建议的,本文从CORS的角度区分了“简单请求”和“非简单请求”的概念:
https://codeburst.io/cors-story-of-requesting-twice-85219da7172d
Authorization从 CORS 的角度来看,我的标头中和 的存在Organization使我的 HTTP 请求成为“非简单请求”,并导致fetch()触发 GET 和 OPTION 请求,其中 OPTION 请求被称为 CORS 飞行前请求。正如 spencedev 指出的,我的 golang 代码
router.HandleFunc("/page", page.Search).Methods("GET","OPTIONS")
Run Code Online (Sandbox Code Playgroud)
说page.Search应该处理 GET 和 OPTIONS 请求。
正如sberry指出的,Gorilla 库有一个处理 CORS 的包。下面是使用 Gorilla CORS 处理程序的 spencedev 答案的替代方案
// main.go
package main
import (
"route/page"
"github.com/gorilla/mux"
"github.com/gorilla/handlers"
"log"
"net/http"
)
func main() {
router := mux.NewRouter()
router.HandleFunc("/page", page.Search).Methods("GET")
headersOk := handlers.AllowedHeaders([]string{"Content-Type","Authorization","Organization"})
originsOk := handlers.AllowedOrigins([]string{"*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
log.Fatal(http.ListenAndServe(":8000", handlers.CORS(originsOk, headersOk, methodsOk)(router)))
}
// route/page.go
package page
import (
"net/http"
"log"
)
func Search(w http.ResponseWriter, r *http.Request) {
log.Println(r.Header.Get("authorization"))
log.Println("Hello World")
w.Write([]byte("{}"))
return
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
126 次 |
| 最近记录: |