Golang预检请求是干嘛的?

阅读次数 19

我发送了个Put请求,也配置了跨域处理,但是发现我明明发送了Put请求,结果后端会平白无故多一个OPTIONS请求,这是为什么?预检请求是否是必要的?

1 Answers

在Web开发中,特别是在涉及到跨源资源共享(CORS, Cross-Origin Resource Sharing)时,你可能会遇到一种称为“预检请求”的HTTP OPTIONS请求。这种请求是由浏览器自动发起的,以确定实际的请求(例如PUT、POST等)是否可以安全地发送到服务器。

为什么会有预检请求

当你的请求包含某些特定的条件时,比如设置了自定义头部(Custom Headers)、使用了非简单的方法(如PUT、DELETE)或非简单的模式(如application/json),浏览器会自动发起一个预检请求(OPTIONS方法)。这个预检请求是为了检查服务器是否允许客户端执行实际的请求。服务器需要正确响应这个预检请求,才能继续执行后续的实际请求。

预检请求的必要性

预检请求对于确保安全性是非常必要的。它允许服务器控制哪些跨源请求是可以被接受的,从而帮助防止潜在的安全威胁。

如何处理预检请求

为了使你的API能够正确处理预检请求,在服务器端你需要对OPTIONS方法进行适当的处理。具体来说,你需要:

  1. 响应预检请求:设置正确的响应头信息,告诉浏览器实际请求可以被发送。
  2. 设置Access-Control-Allow-Methods:指定允许的HTTP方法。
  3. 设置Access-Control-Allow-Headers:如果请求包含了自定义头部,你需要在这里列出这些头部。
  4. 设置Access-Control-Max-Age:可选,用来指定预检请求的结果可以缓存多久。

举个例子,在Go语言中,你可以这样处理预检请求:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // 实际的请求逻辑
}

func optionsHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
    w.Header().Set("Access-Control-Allow-Origin", "*") // 或者指定允许的源
    if r.Method == "OPTIONS" {
        w.WriteHeader(http.StatusOK)
        return
    }
    handler(w, r)
}

func main() {
    http.HandleFunc("/", optionsHandler)
    fmt.Println("Server started at :8080")
    http.ListenAndServe(":8080", nil)
}

在这个例子中,optionsHandler函数首先处理OPTIONS请求,并设置了相应的CORS头信息。然后,根据请求的方法决定是否调用handler函数来处理实际的请求。

通过这种方式,你可以确保浏览器发起的预检请求得到正确的响应,从而允许实际的PUT请求被发送到服务器。

测试发现跨域请求中除了第一次会有个Options "预检请求外",预检通过后,会进行正常的(POST,PUT等)请求,但是这个过程也要设置Access-Control-Allow-Origin,一般在中间键设置,不然预检通过后还是会报未设置Access-Control-Allow-Origin的相关错误