如何使用 Go 代理状态为 OK 的预检请求?

bai*_*idz 4 go

给定客户端发出 HTTP 请求

<!DOCTYPE html>
<html>
    <body>
        <script>
            fetch('http://localhost:3000/messages', {
                method: 'POST',
                headers: { 'content-type': 'application/json' },
                body: JSON.stringify({ data: 'foo' })
            })
            .then(async response => {
                console.log(await response.json());
            });
        </script>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

API服务器不处理请求,请求处理程序应充当代理并将请求发送到另一台服务器

import (
    "net/http"
    "net/http/httputil"
    "net/url"
)

func main() {
    mux := http.NewServeMux()

    mux.HandleFunc("/messages", handleRequest)

    http.ListenAndServe(":3000", mux)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "*")
    w.Header().Set("Access-Control-Allow-Methods", "*")

    targetUrl, _ := url.Parse("http://localhost:3001/messages")

    proxy := httputil.NewSingleHostReverseProxy(targetUrl)
    proxy.ServeHTTP(w, r)
}
Run Code Online (Sandbox Code Playgroud)

目标服务器应该处理请求并发回响应

import (
    "encoding/json"
    "net/http"
)

func main() {
    mux := http.NewServeMux()

    mux.HandleFunc("/messages", handleRequest)

    http.ListenAndServe(":3001", mux)
}

func handleRequest(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "*")
    w.Header().Set("Access-Control-Allow-Methods", "*")

    w.WriteHeader(http.StatusOK)

    json.NewEncoder(w).Encode("bar")
}
Run Code Online (Sandbox Code Playgroud)

我启动两台服务器并运行 .html 文件,我希望

酒吧

在控制台中。但不幸的是我得到了错误

从源“null”获取“http://localhost:3000/messages”的访问已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有 HTTP 正常状态。

在此输入图像描述

有人知道如何解决这个问题吗?

sam*_*eri 5

您需要添加不同的路径来处理代理中的预检请求。这就是你的代理的样子:

func handleRequest(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Header().Set("Access-Control-Allow-Headers", "*")
    w.Header().Set("Access-Control-Allow-Methods", "*")

    if r.Method == "OPTIONS" {
        w.WriteHeader(http.StatusOK)
        return
    }
    targetUrl, _ := url.Parse("http://localhost:3001")

    proxy := httputil.NewSingleHostReverseProxy(targetUrl)
    proxy.ServeHTTP(w, r)
}
Run Code Online (Sandbox Code Playgroud)

注意变化:

  1. OPTION请求(预检)不会传递到服务器,您只需通过发送OK状态来接受它们。

  2. (与 CORS 问题无关)目标 url 不应包含/message部分。路径部分已存在于您的请求中,您不应重复它。

您还需要更改服务器代码并删除这些标头:

// w.Header().Set("Access-Control-Allow-Origin", "*")
// w.Header().Set("Access-Control-Allow-Headers", "*")
// w.Header().Set("Access-Control-Allow-Methods", "*")
Run Code Online (Sandbox Code Playgroud)

它们已经由代理设置。服务器不再响应网络浏览器。

  • 注意:并非所有“OPTIONS”请求都是预检请求。 (2认同)