2014-04-19 22 views
8

Tôi không biết tại sao proxy ngược lại này không hoạt động. Tôi đã nhìn thấy một số ví dụ và tôi không thể tìm thấy bất cứ điều gì sai trái với nó.golang ReverseProxy không hoạt động

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

Nó ghi:

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

Nếu tôi bỏ ghi chú dòng định nghĩa lại Schema được thông báo lỗi trở thành:

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

Nếu tôi bỏ ghi chú dòng định nghĩa lại chủ nhà cũng có, sau đó máy chủ đích trở thành stackoverflow.com (ý tôi là, nó không bao giờ sử dụng "myrealserver.com").

Nếu tôi yêu cầu mylocalhost.com:8080/somepath (hoặc thậm chí /) thì tôi nhận được 404 từ Stackoverflow, cho dù stackoverflow.com/somepath có tồn tại hay không. Nó nói:

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

Nó không tự động dịch tiêu đề Máy chủ.

Nếu sau đó, tôi bỏ ghi chú dòng đặt (và cột còn lại in) Tiêu đề "Máy chủ". Sau đó, tôi có thể đọc "stackoverflow.com" trong nhật ký, nhưng tôi vẫn nhận được cùng một trang 404 báo cáo rằng tôi đang cố truy cập "mylocalhost.com".

Tôi đang sử dụng go1.2.1 linux/amd64

Làm thế nào là nó mà tôi đang phải làm cho nội dung chương trình như là một proxy?

Trả lời

9

Nhờ Alex từ Golang-nut, tôi có câu trả lời ngay bây giờ.

Đây là những gì Alex cho biết:

Chỉ cần thiết lập http.Request.Host [và kế hoạch] trong Giám đốc để có được làm việc này: http://play.golang.org/p/I17ZSM6LQb

Nếu bạn đọc nguồn cho SingleHostReverseProxy (http://golang.org/src/pkg/net/http/httputil/reverseproxy.go#L61), nó thiết lập Giám đốc riêng của mình mà bạn đang ghi đè. Vì vậy, bạn cần phải reimplement những gì nó đã làm cộng với sự thay đổi Host thêm.

Dù sao, điều đó không giải quyết được phần đầu của vấn đề: máy chủ đích vẫn nhận được "localhost: 8080" làm tên Máy chủ HTTP, vì vậy tôi đã thực hiện nó mà không cần gói ReverseProxy, chỉ với http và một RoundTripper, cộng với một chức năng trợ giúp sao chép tất cả các tiêu đề:

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

Bây giờ tôi có thể thấy StackOverflow hoặc bất kỳ trang web nào khác được cho là như thế nào.
Tôi vẫn đang làm việc trên các cuộc gọi POST, vì vậy đây là một công việc đang được tiến hành.

Các vấn đề liên quan