dpg98445 2017-11-24 14:59
浏览 220
已采纳

如果请求路径包含其他斜杠,则Golang将“ 301永久移动”

I have been using golang's default http.ServeMux for http route handling.

wrap := func(h func(t *MyStruct, w http.ResponseWriter, r *http.Request)) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        h(t, w, r)
    }
}

// Register handlers with default mux
httpMux := http.NewServeMux()
httpMux.HandleFunc("/", wrap(payloadHandler))

Assume this server is accessible via http://example.com/

Very few of my client's requests were of path http://example.com/api//module (note the extra slash) which is redirected as 301 Moved Permanently. Exploring inside golang's http ServeMux.Handler(r *Request) function, seems it's intended.

path := cleanPath(r.URL.Path)
// if there is any change between actual and cleaned path, the request is 301 ed
if path != r.URL.Path {
    _, pattern = mux.handler(host, path)
    url := *r.URL
    url.Path = path
    return RedirectHandler(url.String(), StatusMovedPermanently), pattern
}

I've looked into other similar issue.

go-web-server-is-automatically-redirecting-post-requests

Above qn has problem with redundant / in register pattern itself, but my use case is not with register pattern (in some nested path which is irrelevent to register pattern)

Problem is, since my client's requests are POST, browsers handle 301 with new GET request with exact query params and POST body. But change in the HTTP method causes the request to fail.

I have already instructed client to fix the redundant / in url, but the fix might take few (?) weeks to be deployed in all client locations.

Also these redundant / are handled fine in Apache Tomcat, but fails only in golang server. So is this the intended behaviour in my use case (redundant / in nested path) with golang or possible bug?

I am thinking of way to override the Handler func of ServeMux, but it won't be useful since Handler calls are made internally. Looking to disable this 301 behaviour, help would be appreciated.

Relevant links

http-post-method-is-actally-sending-a-get

  • 写回答

2条回答 默认 最新

  • 普通网友 2017-11-24 15:11
    关注

    The clean and redirect is intended behavior.

    Wrap the mux with a handler that removes the double slashes:

    type slashFix struct {
        mux http.Handler
    }
    
    func (h *slashFix) ServeHTTP(w http.ResponseWriter, r *http.Request) {
        r.URL.Path = strings.Replace(r.URL.Path, "//", "/", -1)
        h.mux.ServeHTTP(w, r)
    }
    

    Use it like this:

    httpMux := http.NewServeMux()
    httpMux.HandleFunc("/", wrap(payloadHandler))
    http.ListenAndServe(addr, &slashFix{httpMux})
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错
  • ¥15 单片机学习顺序问题!!
  • ¥15 ikuai客户端多拨vpn,重启总是有个别重拨不上