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 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘