2014-04-19 8 views
8

Ich weiß nicht, warum dieser Reverse-Proxy nicht funktioniert. Ich habe mehrere Beispiele gesehen und kann nichts falsch finden.Golang ReverseProxy funktioniert nicht

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

Es protokolliert:

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 "" 

Wenn ich Kommentar- der Zeile, die das Schema der Fehlermeldung wird neu definiert:

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

Wenn ich Kommentar- der Zeile, die auch den Host neu definiert, dann Der Zielserver wird stackoverflow.com (ich meine, er verwendet nie "myrealserver.com").

Wenn ich nach mylocalhost.com:8080/somepath (oder sogar /) frage, bekomme ich einen 404 von Stackoverflow, egal ob stackoverflow.com/somepath existiert oder nicht. Es sagt:

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

Es übersetzt den Host-Header nicht automatisch.

Wenn ich dann die Zeile auskommentieren, die den Header "Host" setzt (und den anderen druckt). Dann kann ich "stackoverflow.com" im Protokoll lesen, aber ich bekomme immer noch das gleiche 404-Seiten-Reporting, dass ich versuche auf "mylocalhost.com" zuzugreifen.

Ich verwende go1.2.1 linux/amd64

Wie kommt es, dass soll ich das Programm funktioniert als Proxy machen?

Antwort

9

Dank Alex von Golang-Nuts, ich habe jetzt die Antwort.

Dies ist, was Alex sagte:

Nur müssen http.Request.Host um [und Schema] in dem Direktor dieses Funktion zu erhalten: http://play.golang.org/p/I17ZSM6LQb

Wenn Sie die Quelle für SingleHostReverseProxy lesen (http://golang.org/src/pkg/net/http/httputil/reverseproxy.go#L61), es setzt seinen eigenen Direktor, den Sie überschreiben. Sie müssen also Reimplementieren, was es bereits tut und den zusätzlichen Host ändern.

Wie dem auch sei, das nicht de-Header Teil des Problems lösen: der Ziel-Server wurde noch empfangen „localhost: 8080“ als HTTP-Host-Namen, also tat ich es ohne die Reverse Proxy-Paket, nur mit http und ein RoundTripper, sowie eine Hilfsfunktion, die kopiert alle Header:

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

Jetzt bin in der Lage zu mir Stackoverflow oder jede andere Seite zu sehen, wie es sein soll ist.
Ich arbeite immer noch an POST-Anrufe, also ist dies eine Arbeit in Arbeit.

Verwandte Themen