Connection hangs when sending large file using io.Pipe to pCloud

173 views Asked by At

I have a weird issue with this code:

func PrepareFileUpload(filePath, url string) (*http.Request, error) {
    pr, pw := io.Pipe()
    mpw := multipart.NewWriter(pw)

    go func() {
        defer pw.Close()
        
        part, err := mpw.CreateFormFile("file", filepath.Base(filePath))
        if err != nil {
            return
        }

        file, err := os.Open(filePath)
        if err != nil {
            return
        }
        defer file.Close()

        if _, err = io.Copy(part, file); err != nil {
            return
        }

        err = mpw.Close()
        if err != nil {
            return
        }
    }()

    req, err := http.NewRequest("POST", url, pr)
    req.Header.Set("Content-Type", mpw.FormDataContentType())

    return req, err
}

which I use like this:

filePath := "foo.bar"

s := []byte("Test file")
ioutil.WriteFile(filePath, s, 0644)

values := url.Values{}
values.Set("folderid", "123456")
values.Set("filename", filepath.Base(filePath))
values.Set("nopartial", "1")

u := url.URL{
    Scheme:   "https",
    Host:     "eapi.pcloud.com",
    Path:     "/uploadfile",
    RawQuery: values.Encode(),
}

req, err := PrepareFileUpload(filePath, u.String())
if err != nil {
    log.Fatal(err)
}

req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", "ACCESS_TOKEN"))

resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

retData, err := ioutil.ReadAll(resp.Body)
if err != nil {
    log.Fatal(err)
}

fmt.Println(string(retData))

For some reason, when used with the pCloud API, this hangs when running http.DefaultClient.Do(req). I have tried creating my own test server in Go, and there are no issues there, so I'm thinking it's some issues with the communication with the Go client and the pCloud server, but I can't figure out what it is (I've tried forcing HTTP/1.1, but no dice).

When uploading files without io.Pipe and with bytes.Buffer instead, everything is OK, but that doesn't work with large files (OOM).

The only warning I get when enabling verbose HTTP debugging is: 2022/04/21 10:43:29 http2: Transport failed to get client conn for eapi.pcloud.com:443: http2: no cached connection was available This doesn't happen when I force HTTP/1.1, but the connection still hangs, so I'm not sure how relevant this error is.

Does anyone have any idea what could be the cause and how to fix it? Any help is appreciated.

0

There are 0 answers