resty icon indicating copy to clipboard operation
resty copied to clipboard

Big file as request body

Open Myriad-Dreamin opened this issue 2 years ago • 4 comments

I'm uploading a file as request body with size of 4GB and found that resty copies full file content into memory (to handle http.Request.GetBody callback?). However, it is not necessary because net/http.Client only views the body as an io.ReadCloser.

https://github.com/go-resty/resty/blob/7dda6159eceee10c6cacc6f9d1637042f67423b0/middleware.go#L521-L543

After reading closed issue and full code of resty, no api can help me avoid the http client reading all file content. It is expected that resty can expose a stream-like api or handle a cloneable reader implicitly to get request retrying functionality.

    client.R().SetClonableBody(reqBody.Reader)

or

    sink, err := detectBodyCloner(r) // replace getBodyCopy
    if err != nil && err != ErrBodyIsNotCloneable {
        return err
    }

    var bodyIsNotCloneable = err == ErrBodyIsNotCloneable

    // assign get body func for the underlying raw request instance
    r.RawRequest.GetBody = func() (io.ReadCloser, error) {
        if sink != nil {
            cReader := sink.Clone()
            if reader, ok := cReader.(io.Reader); ok {
                return ioutil.NopCloser(reader), nil
            }
            if reader, ok := cReader.(io.ReadCloser); ok {
                return reader, nil
            }
            return nil, ErrBodyIsNotStream
        }
        if bodyIsNotCloneable {
            return nil, ErrBodyIsNotCloneable
        }
        return nil, nil
    }

The second approach is better in the case of net/http.Client never calling GetBody callback

Myriad-Dreamin avatar Dec 04 '21 05:12 Myriad-Dreamin

I need it, too. I currently do this by storing the file and then streaming the read.

kklinan avatar Mar 09 '22 11:03 kklinan

I need the ability to upload files of many GB, thus a stream-like implementation is mandatory. @kklinan could you please post your fix here? Thanks!

florentgluck avatar Jul 26 '22 22:07 florentgluck

this can help you: https://github.com/gospider007/requests/blob/master/test/request/file_test.go

gospider007 avatar Nov 28 '23 13:11 gospider007

I have just run into this and will have to jump libraries—a bit of a shame. Trying to copy an io.Reader into memory vs streaming is a really bad assumption.

I looked, and I think both https://github.com/monaco-io/request and https://github.com/imroc/req handle this correctly.

pcfreak30 avatar Jan 21 '24 04:01 pcfreak30