Go: How to combine two (or more) http.ServeMux?

后端 未结 2 2070
再見小時候
再見小時候 2021-02-06 14:24

Given that you have two instances of http.ServeMux, and you wish for them to be served at the same port number, like so:

    muxA, muxB http.ServeMu         


        
相关标签:
2条回答
  • 2021-02-06 14:31

    The SeverMux type is itself a http.Handler, therefore you can nest them easily. For example:

    mux := NewServeMux()
    mux.AddHandler("server1.com:8080/", muxA)
    mux.AddHandler("server2.com:8080/", muxB)
    

    I'm not quite sure what you mean exactly with "combining" them. If you want to try one handler first and then another one in case of 404, you might do it like this (untested):

    mux := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        rec := httptest.NewRecorder()
        rec.Body = &bytes.Buffer{}
        muxA.ServeHTTP(rec, r)
        if rec.Code == 404 {
            muxB.ServeHTTP(w, r)
            return
        }
        for key, val := range rec.HeaderMap {
            w.Header().Set(key, val)
        }
        w.WriteHeader(rec.Code)
        rec.Body.WriteTo(w)
    })
    

    This has obviously some disadvantages like storing the whole response in memory. Alternatively, if you don't mind calling your handler twice, you can also set rec.Body = nil, check just rec.Code and call muxA.ServeHTTP(w, r) again in case of success. But it's probably better to restructure your application so that the first approach (nested ServerMux) is sufficient.

    0 讨论(0)
  • 2021-02-06 14:46

    Because an http.ServeMux is also an http.Handler you can easily nest one mux inside another, even on the same port and same hostname. Here's one example of doing that:

    rootMux := http.NewServeMux()
    subMux := http.NewServeMux()
    
    // This will end up handling /top_path/sub_path
    subMux.HandleFunc("/sub_path", myHandleFunc)
    
    // Use the StripPrefix here to make sure the URL has been mapped
    // to a path the subMux can read
    rootMux.Handle("/top_path/", http.StripPrefix("/top_path", subMux))
    
    http.ListenAndServe(":8000", rootMux)
    

    Note that without that http.StripPrefix() call, you would need to handle the whole path in the lower mux.

    0 讨论(0)
提交回复
热议问题