2014-01-21 3 views
5

Я создал reverse proxy так:Как читать ответ от 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)) 
} 

И это работает, как ожидалось со стороны клиента, но я хотел бы прочитать ответ от прокси-сервера, как я могу это сделать?

+0

Вы пытались удержать соединение? Или это будет слишком низкий уровень? – Volker

+0

Вы хотите прочесть ответ от прокси-сервера на своем сервере? –

+0

Я, я хочу, чтобы прочитать форму ответа прокси, чтобы сохранить ее в кеше ...: P – OscarRyz

ответ

9

Сеть/пакет http действительно гибкий. Вы можете заменить default Transport 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) { 

    // 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 
} 
+0

Это не сработало. Если я использую тело, мой конечный клиент ничего не получит. Если я прокомментирую вызов ReadAll, он работает (но я не получаю вывод). Смотрите: http://play.golang.org/p/pu_hCabebY – OscarRyz

+0

Это хороший момент. Я изменил свой ответ на создание нового буфера из байтов тела и завернул его в NopCloser (чтобы он реализовал интерфейс ReadCloser), а затем установил свойство Body ответа. Там могут быть лучшие подходы, но я не думаю, что это плохо. – Tyson

+2

Взгляните на [golang.org/pkg/net/http/httputil/#DumpResponse](http://golang.org/pkg/net/http/httputil/#DumpResponse). Либо он сделает все, что вам нужно, либо предоставит полный пример того, как копировать ответ. –

Смежные вопросы