如何使用NewSingleHostReverseProxy处理错误

时间:2019-07-12 01:05:36

标签: http go reverse-proxy

我正在尝试做一个负载均衡器来研究一些go软件包。

我想在请求超时时处理错误,或者给出404错误,但找不到解决方法。

func main() {
    // start server
    http.HandleFunc("/", handleRequestAndRedirect)

    if err := http.ListenAndServe(getListenAddress(), nil); err != nil {
        panic(err)
    }
}

func handleRequestAndRedirect(res http.ResponseWriter, req *http.Request) {

    ur, _ := url.Parse("https://www.instagram.com/")
    proxy := httputil.NewSingleHostReverseProxy(ur)
    // Update the headers to allow for SSL redirection
    req.URL.Host = ur.Host
    req.URL.Scheme = ur.Scheme
    req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
    req.Host = ur.Host
    req.Header.Set("Key", "Teste")

    proxy.ServeHTTP(res, req)

}

2 个答案:

答案 0 :(得分:1)

当我最终在这里寻找一种方法来处理来自代理主机的 404 错误时,我想补充已接受的答案,如果它对登陆此页面的人有帮助的话。

如官方文档 (https://golang.org/pkg/net/http/httputil/#ReverseProxy) 所述:

<块引用>

ModifyResponse 是一个可选函数,用于修改来自后端的 Response。如果后端完全返回响应并带有任何 HTTP 状态代码,则调用它。 如果后端无法访问,则调用可选的 ErrorHandler 而不调用 ModifyResponse。如果 ModifyResponse 返回错误,则调用 ErrorHandler 及其错误值。如果 ErrorHandler 为 nil,则使用其默认实现。

因此,如果您不仅要捕获“真实”错误(主机无法访问),还要捕获来自服务器的错误响应代码(404、500...),您应该使用 ModifyResponse 检查响应状态代码并返回一个错误,然后您的 ErrorHandler 函数会捕获该错误。接受的答案示例变为:

func handleRequestAndRedirect(res http.ResponseWriter, req *http.Request) {
    
    ur, _ := url.Parse("https://www.instagram.com/")
    proxy := httputil.NewSingleHostReverseProxy(ur)
    // Update the headers to allow for SSL redirection
    req.URL.Host = ur.Host
    req.URL.Scheme = ur.Scheme
    req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
    req.Host = ur.Host
    req.Header.Set("Key", "Teste")

    proxy.ErrorHandler = ErrHandle
    proxy.ModifyResponse = ModifyResponse
    proxy.ServeHTTP(res, req)
}

func ModifyResponse(res *http.Response) error {
    if res.StatusCode == 404 {
        return errors.New("404 error from the host")
    }
    return nil
}  

func ErrHandle(res http.ResponseWriter, req *http.Request, err error) {
    fmt.Println(err)
}  

答案 1 :(得分:0)

使用proxy.ErrorHandler

ErrorHandler func(http.ResponseWriter,* http.Request,错误)

  func handleRequestAndRedirect(res http.ResponseWriter, req *http.Request) {

        ur, _ := url.Parse("https://www.instagram.com/")
        proxy := httputil.NewSingleHostReverseProxy(ur)
        // Update the headers to allow for SSL redirection
        req.URL.Host = ur.Host
        req.URL.Scheme = ur.Scheme
        req.Header.Set("X-Forwarded-Host", req.Header.Get("Host"))
        req.Host = ur.Host
        req.Header.Set("Key", "Teste")

        proxy.ErrorHandler = ErrHandle
        proxy.ServeHTTP(res, req)
    }

    func ErrHandle(res http.ResponseWriter, req *http.Request, err error) {
        fmt.Println(err)
    }