Go: Как совместить два (или более) http.ServeMux?

Учитывая, что у вас есть два случая http.ServeMuxи вы хотите, чтобы они обслуживались с одним и тем же номером порта, например:

    muxA, muxB http.ServeMux
    //initialise muxA
    //initialise muxB
    combinedMux := combineMux([muxA, muxB])
    http.ListenAndServe(":8080", combinedMux)

Как можно было бы написать combinedMux функция, как описано выше?

... или есть альтернативный способ сделать то же самое?

2 ответа

Потому что http.ServeMux также http.Handler Вы можете легко вложить один мультиплексор в другой, даже на тот же порт и то же имя хоста. Вот один из примеров этого:

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)

Обратите внимание, что без этого http.StripPrefix() вызов, вам нужно будет обрабатывать весь путь в нижнем мультиплексоре.

Тип SeverMux сам по себе является http.Handler, поэтому вы можете легко их вложить. Например:

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

Я не совсем уверен, что вы имеете в виду именно под "объединением" их. Если вы хотите сначала попробовать один обработчик, а затем другой в случае 404, вы можете сделать это следующим образом (не проверено):

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

Это, очевидно, имеет некоторые недостатки, такие как хранение всего ответа в памяти. Кроме того, если вы не против дважды вызвать ваш обработчик, вы также можете установить rec.Body = nilпроверь просто rec.Code и позвонить muxA.ServeHTTP(w, r) снова в случае успеха. Но, вероятно, лучше реструктурировать ваше приложение, чтобы первого подхода (вложенного ServerMux) было достаточно.

Другие вопросы по тегам