代码之家  ›  专栏  ›  技术社区  ›  The Coder

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

  •  4
  • The Coder  · 技术社区  · 7 年前

    我一直在使用golang的默认值 http.ServeMux 用于http路由处理。

    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))
    

    假设此服务器可以通过 http://example.com/

    我客户的请求中很少有路径问题 http://example.com/api//module (注意额外的斜杠)重定向为 301 Moved Permanently . 探索golang的http内部 ServeMux.Handler(r *Request) 功能,似乎是有意的。

    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
    }
    

    我还研究了其他类似的问题。

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

    以上qn存在冗余问题 / 在寄存器模式本身中,但我的用例不在寄存器模式中(在一些与寄存器模式无关的嵌套路径中)

    问题是,因为我客户的要求是 POST ,浏览器使用新的 GET 具有精确查询参数和POST正文的请求。但是HTTP方法中的更改会导致请求失败。

    我已经指示客户修复多余的 / 在url中,但修复可能需要几(?)在所有客户端位置部署数周。

    这些也是多余的 / 处理得很好 Apache Tomcat ,但仅在golang服务器中失败。那么,这是我用例中的预期行为吗(多余的 /

    我在想办法超越 Handler 的函数 ServeMux ,但它将不再有用 处理程序 内部通话。如果希望禁用此301行为,我们将不胜感激。

    相关链接

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

    2 回复  |  直到 7 年前
        1
  •  7
  •   Reverend Homer Bayta Darell    5 年前

    清除和重定向是预期行为。

    用移除双斜杠的处理程序包装多路复用器:

    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)
    }
    

    这样使用:

    httpMux := http.NewServeMux()
    httpMux.HandleFunc("/", wrap(payloadHandler))
    http.ListenAndServe(addr, &slashFix{httpMux})
    
        2
  •  1
  •   The Coder    7 年前

    接受的答案解决了问题

    还有一种方法是使用 Gorilla mux 和设置 SkipClean(true) . 但是一定要知道它的副作用 doc

    SkipClean定义了新路由的路径清理行为。初始值为false。用户应注意哪些路线未清理。当为true时,如果路由路径为“/path//to”,则它将保留双斜杠。如果您有类似于:/fetch的路由,这将非常有用/ http://xkcd.com/534/

    如果为false,则将清除路径,因此/fetch/ http://xkcd.com/534/ 将成为/fetch/http/xkcd。com/534

    func (r *Router) SkipClean(value bool) *Router {
        r.skipClean = value
        return r
    }