golang中http POST的预检问题

Posted

技术标签:

【中文标题】golang中http POST的预检问题【英文标题】:Preflight issue with http POST in golang 【发布时间】:2015-10-03 10:27:26 【问题描述】:

我正在使用 mux 包并且有这个代码:

func saveConfig(w http.ResponseWriter, r *http.Request) 
    if origin := r.Header.Get("Origin"); origin != "" 
        w.Header().Set("Access-Control-Allow-Origin", origin)
        fmt.Println("Origin: " + origin)
        w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
    
    // Stop here if its Preflighted OPTIONS request
    if r.Method == "OPTIONS" 
        return
    

    body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1048576))
    if err != nil 
        fmt.Println("Error: %s\n", err)
        w.WriteHeader(http.StatusInternalServerError)
        return
    

    fmt.Println("JSON body:" + string(body))
    if err := r.Body.Close(); err != nil 
        panic(err)
    

    w.WriteHeader(http.StatusCreated)

它在 IE 上运行良好,但 chrome preflight 正在发送一个 OPTIONS 方法,我收到了 404 响应。任何帮助将不胜感激。

【问题讨论】:

404 可能意味着它没有找到处理程序。检查请求的路径是否与您的处理程序的路由匹配。 Request Header:Accept:*/* Accept-Encoding:gzip, deflate, sdch Accept-Language:en-US,en;q=0.8 Access-Control-Request-Headers:accept, content-类型 Access-Control-Request-Method:POST Connection:keep-alive Host:localhost:8080 Origin:localhost:63342Referer:localhost:63342/Main/app User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (Khtml,像壁虎)Chrome/42.0.2311.90 Safari/537.36 显示用于注册路由的代码和从浏览器输入的 URL。此外,使用godoc.org/net/http#MaxBytesReader 代替 io.LimitReader。 io.LimitReader 不会阻止服务器访问整个请求正文。 如果我在路由器中将方法从 POST 更改为 OPTIONS,我会收到状态码 200 func NewRouter() *mux.Router router := mux.NewRouter().StrictSlash(true) for _, route := range routes var handler http.Handler handler = route.HandlerFunc / /handler = commonlibrary.Logger(handler, route.Name) 路由器。方法(路线。方法)。路径(路线。模式)。名称(路线。名称)。 Handler(handler) 返回路由器 【参考方案1】:

代码注册 POST,但不注册 OPTIONS。一种方法是将您的代码更改为以下内容:

func NewRouter() *mux.Router  
    router := mux.NewRouter().StrictSlash(true) 
    for _, route := range routes  
        var handler http.Handler 
        handler = route.HandlerFunc
        handler = commonlibrary.Logger(handler, route.Name) 
        return router.Methods(route.Method, "OPTIONS").Path(route.Pattern).Name(route.Name).Handler(handler)
 

这将为所有处理程序添加 OPTIONS。另一种方法是将 Route Method 字段更改为 Methods []string 并将路由器创建为:

return router.Methods(route.Methods..., "OPTIONS").Path(route.Pattern).Name(route.Name).Handler(handler)

这将允许您将 OPTIONS 添加到处理程序的子集。

另一种方法是为 OPTIONS 注册一个单独的处理程序:

 Route"saveConfig", "OPTIONS", "/saveConfig", preflight

【讨论】:

我选择了以下选项:Route"saveConfig", "OPTIONS", "/saveConfig", preflight 现在,如果我从 Angularjs $http.post('localhost:8080/saveConfig', data = JSON.stringify(custconfig)) 我得到了 HTTP/1.1 200 OK,但它没有调用 POST。看起来只有 Options 是从客户端调用的 这是我的预检代码: func saveConfigPreFlight(w http.ResponseWriter, r *http.Request) if origin := r.Header.Get("Origin"); origin == "localhost:8080" w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Methods", "POST" ) w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") // 如果是就停在这里预检 OPTIONS 请求 if r.Method == "OPTIONS" return saveConfig(w, r) 从预检处理程序中删除了 saveconfig(w,r) 并且 POST 现在工作正常。但在 Chrome 上我仍然看到错误:1 XMLHttpRequest cannot load localhost:8080/saveConfig。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此不允许访问 Origin 'localhost:63342'。

以上是关于golang中http POST的预检问题的主要内容,如果未能解决你的问题,请参考以下文章

带有 Windows 身份验证预检问题的 Angular 4 HTTP POST [重复]

已启用 CORS,但在 POST JSON 时,预检响应的 HTTP 状态代码 404 无效

HTTP 预检 (OPTIONS) 请求仅在 IE 中失败

预检响应在角度 4 中具有无效的 HTTP 状态代码 500

Angular CORS 简单请求在 POST 中触发带有 Authorization 标头的预检

如何在AngularJS中丢弃预检响应