如何读取NewSingleHostReverseProxy的响应?

huangapple go评论96阅读模式
英文:

How to read the response from a NewSingleHostReverseProxy

问题

我创建了一个类似这样的反向代理

func ProxyFunc(w http.ResponseWriter, r *http.Request) {
    u, err := url.Parse("http://mynetworkserverhere:8957/some/path/here/")
    if err == nil {
        proxy := httputil.NewSingleHostReverseProxy(u)
        proxy.ServeHTTP(w, r)
        // ????
    } else {
        w.Write([]byte(err.Error()))
    }
}

然后从主函数中调用它:

func main() {
    log.Printf("Starting...")
    http.HandleFunc("/", ProxyFunc)
    log.Fatal(http.ListenAndServe(":6060", nil))
}

从客户端的角度来看,它按预期工作,但我想从代理中读取响应,我该如何做到这一点?

英文:

I've created a reverse proxy like this:

func ProxyFunc(w http.ResponseWriter, r *http.Request) {
	u, err := url.Parse("http://mynetworkserverhere:8957/some/path/here/")
	if err == nil {
		proxy := httputil.NewSingleHostReverseProxy(u)
		proxy.ServeHTTP(w, r)
		//????

	} else {
		w.Write([]byte(err.Error()))
	}
}

And invoke it from main:

func main() {
   log.Printf("Starting...")
   http.HandleFunc("/", ProxyFunc)
   log.Fatal(http.ListenAndServe(":6060", nil))
}

And it works as expected from the client side, but I'd like to read the response from the proxy, how can I do that?

答案1

得分: 9

net/http包非常灵活。您可以用自己的方式替换ReverseProxy的默认传输,只需使用DefaultTransport即可。然后,您可以拦截RoundTrip调用并执行任何您想要的操作。

package main

import (
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

func main() {
	log.Printf("Starting...")
	http.HandleFunc("/", someFunc)
	log.Fatal(http.ListenAndServe(":6060", nil))
}

func someFunc(w http.ResponseWriter, r *http.Request) {

	// 将请求主机更改为匹配目标
	r.Host = "you.host.here:port"
	u, _ := url.Parse("http://you.host.here:port/some/path/")
	proxy := httputil.NewSingleHostReverseProxy(u)
	// 如果需要,您可以选择捕获/包装传输(例如,如果传输已被中间件替换)。示例:
	// proxy.Transport = &myTransport{proxy.Transport}
	proxy.Transport = &myTransport{}

	proxy.ServeHTTP(w, r)
}

type myTransport struct {
	// 如果要捕获传输,请取消注释此行
	// CapturedTransport http.RoundTripper
}

func (t *myTransport) RoundTrip(request *http.Request) (*http.Response, error) {
	response, err := http.DefaultTransport.RoundTrip(request)
	// 或者,如果您捕获了传输
	// response, err := t.CapturedTransport.RoundTrip(request)

	// httputil包提供了一个DumpResponse()函数,它将将响应体的内容复制到[]byte中并返回它。它还将其包装在ioutil.NopCloser中,并设置响应以传递给客户端。
	body, err := httputil.DumpResponse(response, true)
	if err != nil {
		// 复制响应体失败
		return nil, err
	}

	// 您可能希望检查Content-Type头来决定如何处理响应体。在这种情况下,我们假设它是文本。
	log.Print(string(body))

	return response, err
}

以上是一段使用net/http包的示例代码,它展示了如何替换ReverseProxy的默认传输,并拦截RoundTrip调用以执行自定义操作。

英文:

The net/http package is really flexible. You can replace the default Transport of the ReverseProxy with your own, which just uses the DefaultTransport. Then you can intercept the RoundTrip call and do whatever you'd like.

package main

import (
	"log"
	"net/http"
	"net/http/httputil"
	"net/url"
)

func main() {
	log.Printf("Starting...")
	http.HandleFunc("/", someFunc)
	log.Fatal(http.ListenAndServe(":6060", nil))
}

func someFunc(w http.ResponseWriter, r *http.Request) {

	// change the request host to match the target
	r.Host = "you.host.here:port"
	u, _ := url.Parse("http://you.host.here:port/some/path/")
	proxy := httputil.NewSingleHostReverseProxy(u)
	// You can optionally capture/wrap the transport if that's necessary (for
	// instance, if the transport has been replaced by middleware). Example:
	// proxy.Transport = &myTransport{proxy.Transport}
	proxy.Transport = &myTransport{}

	proxy.ServeHTTP(w, r)
}

type myTransport struct {
	// Uncomment this if you want to capture the transport
	// CapturedTransport http.RoundTripper
}

func (t *myTransport) RoundTrip(request *http.Request) (*http.Response, error) {
	response, err := http.DefaultTransport.RoundTrip(request)
	// or, if you captured the transport
	// response, err := t.CapturedTransport.RoundTrip(request)

	// The httputil package provides a DumpResponse() func that will copy the
	// contents of the body into a []byte and return it. It also wraps it in an
	// ioutil.NopCloser and sets up the response to be passed on to the client.
	body, err := httputil.DumpResponse(response, true)
	if err != nil {
		// copying the response body did not work
		return nil, err
	}

	// You may want to check the Content-Type header to decide how to deal with
	// the body. In this case, we're assuming it's text.
	log.Print(string(body))

	return response, err
}

huangapple
  • 本文由 发表于 2014年1月22日 07:07:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/21270945.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定