2014-10-04 94 views
1

我正在嘗試做一個GET請求,然後將我得到的內容發送到POST請求中的另一個站點。下面的代碼工作正常:發送兩個功能之間的`閱讀器'

func deliver(sourceURL *url.URL, destinationURL *url.URL) { 
    client := &http.Client{} 
    sourceResponse, err := http.Get(sourceURL.String()) 
    if err == nil { 
     body, _ := ioutil.ReadAll(sourceResponse.Body) 
     client.Post(destinationURL.String(), "text/html", strings.NewReader(string(body))) 
    } 
} 

但是這將整個響應讀入內存 - 如何將響應流式傳輸到POST請求?這是我想要的:

func deliver(sourceURL *url.URL, destinationURL *url.URL) { 
    client := &http.Client{} 
    sourceResponse, err := http.Get(sourceURL.String()) 
    if err == nil { 
     client.Post(destinationURL.String(), "text/html", sourceResponse.Body) 
    } 
} 

我會假設這會工作,但它只發送一個空請求(沒有正文)。爲什麼是這樣? client.Post函數是不是實際嘗試讀取響應?

這裏的隨身操場一個例子:http://play.golang.org/p/_EO80aj6wr 發送的dataReader代替sourceResponse.Body作品完美,但在發送sourceResponse.Body直接不起作用。

實例鏈接:

http://localhost:3000/fetch?dest=http://requestb.in/177ji621&src=http://www.google.com 
http://requestb.in/177ji621?inspect 

回答

2

我做了一個小測試程序嘗試了這一點

package main 

import (
    "fmt" 
    "io/ioutil" 
    "log" 
    "net/http" 
    "net/url" 
) 

var client = &http.Client{} 

func httpd() { 
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 
     log.Printf("%s Request from %s", r.Method, r.RemoteAddr) 
     if r.Method == "GET" { 
      fmt.Fprintf(w, "Here is a GET body") 
      return 
     } 
     body, err := ioutil.ReadAll(r.Body) 
     if err != nil { 
      log.Fatalf("body read failed: %v", err) 
     } 
     log.Printf("Body received from %s: %q", r.Method, body) 
    }) 
    log.Fatal(http.ListenAndServe(":8080", nil)) 
} 

func deliver(sourceURL *url.URL, destinationURL *url.URL) { 
    sourceResponse, err := http.Get(sourceURL.String()) 
    if err != nil { 
     log.Fatalf("post failed: %v", err) 
    } 
    postResponse, err := client.Post(destinationURL.String(), "text/html", sourceResponse.Body) 
    if err != nil { 
     log.Fatalf("post failed: %v", err) 
    } 
    postResponse.Body.Close() 
    sourceResponse.Body.Close() 
} 

func main() { 
    go httpd() 
    src, err := url.Parse("http://127.0.0.1:8080/") 
    if err != nil { 
     log.Fatalf("src parse failed: %v", err) 
    } 
    dst, err := url.Parse("http://127.0.0.1:8080/") 
    if err != nil { 
     log.Fatalf("dst parse failed: %v", err) 
    } 
    deliver(src, dst) 
} 

它能正常工作,生產這種輸出

2014/10/04 08:40:26 GET Request from 127.0.0.1:48910 
2014/10/04 08:40:26 POST Request from 127.0.0.1:48911 
2014/10/04 08:40:26 Body received from POST: "Here is a GET body" 

所以這個問題你代碼可能會由你沒有檢查的錯誤 - Post中最可能的錯誤所揭示。

另請注意,如果可以的話,您想重新使用http.Client,這樣您就可以獲得連接池。


更新後審查更新的問題。

我試過我的測試程序http://requestb.in/,它不顯示正文。但我確實看到這個Transfer-Encoding: chunked,所以我懷疑requestb.in不支持分塊傳輸編碼。

如果您提供整個機構的請求然後去設置Content-Length標題,但if you provide a stream然後去使用chunked transfer encoding。即使分塊傳輸編碼是HTTP/1.1規範的非可選部分,也有相當多的服務器不支持它。

+0

不知道爲什麼它不適合我。嘗試檢查所有錯誤,但沒有問題。我可以確認請求正在發送,但主體仍然是空的。 – 2014-10-04 09:16:08

+0

如果您需要更多幫助,請發佈一個演示問題的實例。 – 2014-10-04 10:07:04

+0

我已經在問題中添加了一個Go操場示例 - 看起來像我可以清晰地重現。 – 2014-10-04 10:44:09