2014-04-19 10 views
8

Nie wiem, dlaczego to odwrotne proxy nie działa. Widziałem kilka przykładów i nie mogę znaleźć w tym nic złego.golang ReverseProxy nie działa

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

Loguje:

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

Gdybym odkomentuj linię, która redefiniuje schematu komunikat o błędzie postać:

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

Gdybym odkomentuj linię, która redefiniuje gospodarz również, następnie serwer docelowy staje się stackoverflow.com (to znaczy, nigdy nie używa "myrealserver.com").

Jeśli poproszę o mylocalhost.com:8080/somepath (lub nawet /), otrzymam 404 od Stackoverflow, bez względu na to, czy stackoverflow.com/somepath istnieje czy nie. Jest napisane:

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

Nie tłumaczy automatycznie nagłówka Host.

Jeśli następnie odkomentuję linię, która ustawia (i drugą, która drukuje) nagłówek "Host". Wtedy mogę przeczytać "stackoverflow.com" w dzienniku, ale nadal otrzymuję to samo 404 raportowanie strony, że próbuję uzyskać dostęp do "mylocalhost.com".

Używam go1.2.1 linux/amd64

Jak to jest, że ja powinienem zrobić program działa jako serwer proxy?

Odpowiedz

9

Dzięki Alexowi z Golang-orzechów, mam teraz odpowiedź.

To właśnie Alex powiedział:

wystarczy ustawić http.Request.Host [i schemat] w dyrektora, aby ten robocza: http://play.golang.org/p/I17ZSM6LQb

Jeśli czytasz źródło SingleHostReverseProxy (http://golang.org/src/pkg/net/http/httputil/reverseproxy.go#L61), to ustala własnego Dyrektora, nad którym nadpisujesz. Musisz więc ponownie wykonać to, co już robi, plus dodatkową zmianę Hosta.

W każdym razie to nie rozwiązało części De Header problemu: serwer docelowy wciąż otrzymywał "localhost: 8080" jako nazwę hosta HTTP, więc zrobiłem to bez pakietu ReverseProxy, tylko z http i RoundTripper plus funkcja pomocnika, który kopiuje wszystkie nagłówki:

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

teraz jestem w stanie zobaczyć StackOverflow lub jakąkolwiek inną stronę, jak to powinno być.
Nadal pracuję nad połączeniami POST, więc to jest praca w toku.