2014-04-19 14 views
8

Non so perché questo proxy inverso non funzioni. Ho visto diversi esempi e non riesco a trovare nulla di sbagliato in questo.golang ReverseProxy non funziona

package main 

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

func report(r *http.Request){ 
    log.Print("URL: " + r.URL.Path) 
    log.Print("Scheme: " + r.URL.Scheme) 
    log.Print("Host: " + r.URL.Host) 
    //r.URL.Scheme = "http" 
    //r.URL.Host = "stackoverflow.com" 

    //r.Header.Set("Host", "stackoverflow.com") 
    //log.Print("Header Host: " + r.Header.Get("Host")) 
} 

func main() { 
    proxy := httputil.NewSingleHostReverseProxy(&url.URL{Scheme:"http",Host:"myrealserver.com"}) 
    proxy.Director = report 
    // http.Handle("/", proxy) 
    error := http.ListenAndServe("mylocalhost.com:8080", proxy) 
    if(error != nil) { 
     log.Fatal(error) 
    } 
} 

Si registra:

2014/04/18 21:32:50 URL: /arg/es 
2014/04/18 21:32:50 Scheme: 
2014/04/18 21:32:50 Host: 
2014/04/18 21:32:50 http: proxy error: unsupported protocol scheme "" 

2014/04/18 21:32:51 URL: /favicon.ico 
2014/04/18 21:32:51 Scheme: 
2014/04/18 21:32:51 Host: 
2014/04/18 21:32:51 http: proxy error: unsupported protocol scheme "" 

Se io rimuovere il commento dalla linea che ridefinisce lo schema il messaggio di errore diventa:

2014/04/18 21:38:05 http: proxy error: http: no Host in request URL 

Se io rimuovere il commento dalla linea che ridefinisce l'host anche, quindi il server di destinazione diventa stackoverflow.com (voglio dire, non usa mai "myrealserver.com").

Se chiedo mylocalhost.com:8080/somepath (o even /), ricevo un 404 da Stackoverflow, non importa se stackoverflow.com/somepath esiste o meno. Dice:

Couldn't find mylocalhost.com:8080 
The Q&A site mylocalhost.com:8080 doesn't seem to exist... yet 

Non converte automaticamente l'intestazione Host.

Se poi annullo la riga che imposta (e l'altra che stampa) l'intestazione "Host". Quindi posso leggere "stackoverflow.com" nel registro, ma ottengo comunque la stessa segnalazione di pagina 404 che sto tentando di accedere a "mylocalhost.com".

sto usando go1.2.1 linux/amd64

Come è possibile che dovrei far funzionare il programma come un proxy?

risposta

9

Grazie ad Alex di Golang-nuts, ho la risposta ora.

Questo è quello che Alex ha detto:

solo bisogno di impostare http.Request.Host [e schema] nella direttore per ottenere questo di lavoro: http://play.golang.org/p/I17ZSM6LQb

Se leggete la fonte per SingleHostReverseProxy (http://golang.org/src/pkg/net/http/httputil/reverseproxy.go#L61), è imposta il proprio direttore che si sta ignorando. Quindi è necessario reimplementare ciò che già fa più la modifica dell'host in più.

In ogni caso, che non ha risolto de Header parte del problema: il server di destinazione è stato ancora ricevendo "localhost: 8080" come nome host HTTP, quindi ho fatto senza il pacchetto ReverseProxy, solo con http e un RoundTripper, oltre a una funzione di supporto che copia tutte le intestazioni:

package main 

import (
    "flag" 
    "fmt" 
    "os" 
    "log" 
    "net/http" 
    "io/ioutil" 
) 

var target *string 

func main() { 
    target = flag.String("target", "http://stackoverflow.com", "target URL for reverse proxy") 
    flag.Parse() 
    http.HandleFunc("/", report) 
    log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil)) 
} 

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

    uri := *target+r.RequestURI 

    fmt.Println(r.Method + ": " + uri) 

    if r.Method == "POST" { 
    body, err := ioutil.ReadAll(r.Body) 
    fatal(err) 
    fmt.Printf("Body: %v\n", string(body)); 
    } 

    rr, err := http.NewRequest(r.Method, uri, r.Body) 
    fatal(err) 
    copyHeader(r.Header, &rr.Header) 

    // Create a client and query the target 
    var transport http.Transport 
    resp, err := transport.RoundTrip(rr) 
    fatal(err) 

    fmt.Printf("Resp-Headers: %v\n", resp.Header); 

    defer resp.Body.Close() 
    body, err := ioutil.ReadAll(resp.Body) 
    fatal(err) 

    dH := w.Header() 
    copyHeader(resp.Header, &dH) 
    dH.Add("Requested-Host", rr.Host) 

    w.Write(body) 
} 

func fatal(err error) { 
    if err != nil { 
    log.Fatal(err) 
    os.Exit(1) 
    } 
} 

func copyHeader(source http.Header, dest *http.Header){ 
    for n, v := range source { 
     for _, vv := range v { 
      dest.Add(n, vv) 
     } 
    } 
} 

Ora sono in grado di vedere StackOverflow o qualsiasi altro sito come dovrebbe essere.
Sto ancora lavorando alle chiamate POST, quindi, questo è un work in progress.