douzi1117 2015-08-27 23:59
浏览 1648
已采纳

Golang在路由之前修改HTTP请求参数(例如URL路径)

It's common practice in some cases to pass plain URIs as suffix of the path instead of a query parameter. Here is an example from Internet Archive's Wayback Machine.

https://web.archive.org/web/20150825082012/http://example.com/

In this example, user is requesting a copy of http://example.com/ as captured at 2015-08-25 08:20:12. If we were to implement similar service in Go, we probably would have a router as follows:

http.HandleFunc("/web/", returnArchivedCopy)

Then in the returnArchivedCopy handler function, we will split r.URL.Path (where r is the Request object) to extract the date-time and the target URL. However there is a problem in this style of URL scheme; Go's net/http package calls cleanPath function on the path portion to sanitize it. This sanitization process does various cleanup tasks such as eeliminating . and .. from the path and replace multiple slashes with a single one. This later operation makes sense when because in Unix systems // in the file path are same as /. However this causes an issue in the above described use case as http://example becomes http:/example and the server internally returns a redirect response to the client with the sanitized path.

I am wondering, what are my options in this case? Is there a way to ask HTTP not to sanitize the request path while still utilizing all the default behavior that is shipped with the default (or slightly modified) server, multiplexer, and handler? Or is there a way to modify the request parameters (path in this case) before it hits the multiplexer's routing patterns. If the later is possible, we might try to perform something like URL encoding to avoid the redirect and later decode the URL back in the handler function before extracting desired bits.

I have experimented with some custom handlers and multiplexers, but I am new to Go, hence I was not quite sure how to delegate the routing back to the default handlers after making changes in the request.

  • 写回答

1条回答 默认 最新

  • douzhang6646 2015-08-28 05:10
    关注

    You can implement a wrapper mux, that falls back to the default one, here's a very simple example:

    func main() {
        http.HandleFunc("/blah", func(w http.ResponseWriter, req *http.Request) {
            w.Write([]byte("w00t"))
        })
        http.ListenAndServe(":9090", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
            p := strings.SplitN(req.URL.RequestURI()[1:] /*trim the first slash*/, "/", 3)
            if len(p) != 3 || p[0] != "web" {
                http.DefaultServeMux.ServeHTTP(w, req)
                return
            }
    
            t, err := time.Parse("20060102150405", p[1])
            if err != nil {
                http.Error(w, "invalid time", 400)
                return
            }
            url := p[2]
            fmt.Fprintf(w, "requested url %v @ %v", url, t)
        }))
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Attention is all you need 的代码运行
  • ¥15 一个服务器已经有一个系统了如果用usb再装一个系统,原来的系统会被覆盖掉吗
  • ¥15 使用esm_msa1_t12_100M_UR50S蛋白质语言模型进行零样本预测时,终端显示出了sequence handled的进度条,但是并不出结果就自动终止回到命令提示行了是怎么回事:
  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥30 关于<main>标签页面跳转的问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加
  • ¥15 用ns3仿真出5G核心网网元
  • ¥15 matlab答疑 关于海上风电的爬坡事件检测