Io 在两个函数之间发送“Reader”

Io 在两个函数之间发送“Reader”,io,go,Io,Go,我正在尝试发出一个GET请求,然后在POST请求中将我获得的内容发送到另一个站点。以下代码可以正常工作: func deliver(sourceURL *url.URL, destinationURL *url.URL) { client := &http.Client{} sourceResponse, err := http.Get(sourceURL.String()) if err == nil { body, _ := ioutil.Re

我正在尝试发出一个
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
函数是否实际尝试读取响应

下面是一个在运动场上的例子: 发送
dataReader
而不是
sourceResponse.Body
效果很好,但是直接发送
sourceResponse.Body
不起作用

示例链接:

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

我做了一个小测试程序来尝试这个

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"
因此,代码的问题很可能会被你没有检查的错误暴露出来——最有可能的错误是文章中的错误

还请注意,如果可以,您希望重用
http.Client
,以便获得连接池


查看问题更新后更新

我用
http://requestb.in/
并且它不显示主体。然而,我确实看到了这种
传输编码:chunked
,所以我怀疑
requestb.in
不支持chunked传输编码


如果为请求提供整个正文,则go将设置
内容长度
标题,但go使用。尽管分块传输编码是HTTP/1.1规范的非可选部分,但仍有相当多的服务器不支持它。

不知道为什么它不适合我。尝试检查所有错误,但没有问题。我可以确认请求正在发送,但正文仍然是空的。如果您需要更多帮助,请发布一个演示问题的工作示例。我在问题中添加了一个Go Playder示例-看起来我可以清晰地再现。某种意义上,我猜这可能就是问题所在。但我在围棋测试中也遇到了同样的问题。如果你仍然好奇,代码就在这里:在
fetch.go
fetch\u test.go
中。