Why not set Request.ContentLength beforehand (you know it)?

dmo...@synack.com a következőt írta (2022. január 14., péntek, 18:56:57 
UTC+1):

> Sorry to insist, but I think there's also a performance issue with the 
> current implementation. Given that the service I need to communicate to 
> requires me to send Content-Length header I am forced to read into memory 
> potentially large files that I want to send them, buffering them in one of 
> the three (undocumented!) *structs that are known 
> (*bytes.Buffer, *bytes.Reader or *strings.Reader) instead of being able to 
> just pass the *os.File. Thing is, I could analyze the size of each file, 
> break it down into parts that I can read into memory and make a request for 
> each part that the service would later join into a single file, but that 
> sounds like overkill and also sounds like a lot of work and overhead for 
> something that could be done with a simple io.Reader.
>
> I think that the easiest way to overcome this issue and at the same time 
> not break the promises made would be to do something like:
>
> func readerLength(body io.Reader) (int64, error) {
>         if f, _ := body.(fs.File); f != nil {
>                 if i, err := f.Stat(); err == nil { // discard error and 
> try io.Seeker interface later (it's cheaper to stat instead of seeking)
>                         return i.Size(), nil
>                 }
>         }
>
>         if s, _ := body.(interface { // covers *bytes.Reader and other
>                 Size() int64
>         }); s != nil {
>                 return s.Size(), nil
>         }
>
>         if l, _ := body.(interface { // covers all the three current 
> undocumented items: *bytes.Buffer, *bytes.Reader and *strings.Reader
>                 Len() int
>         }); l != nil {
>                 return int64(l.Len()), nil
>         }
>
>         if s, _ := body.(io.Seeker); s != nil { // covers a lot of other 
> cases, like multipart.File, errors statting *os.File, etc.
>                 cur, err := s.Seek(0, io.SeekCurrent)
>                 if err != nil {
>                         return -1, fmt.Errorf("error checking current 
> position: %w", err)
>                 }
>
>                 end, err := s.Seek(0, io.SeekEnd)
>                 if err != nil {
>                         return -1, fmt.Errorf("error seeking end position: 
> %w", err)
>                 }
>
>                 _, err = s.Seek(cur, io.SeekStart)
>                 if err != nil {
>                         return -1, fmt.Errorf("error going back to initial 
> position: %w", err)
>                 }
>
>                 return end - cur, nil
>         }
>
>         return -1, errors.New("unknown body, don't send the Content-Length 
> header")
> }
>
>
>
> On Friday, September 17, 2021 at 2:23:50 PM UTC-3 Diego Molina wrote:
>
>> Ok, that makes total sense. I'm now using `req.TransferEncoding = 
>> []string{"identity"}` and this behaviour is suppressed, but of course I 
>> still don't get the Content-Length, which is fair.
>>
>> Thanks all!
>>
>> On Fri, Sep 17, 2021 at 2:09 PM Brian Candler <b.ca...@pobox.com> wrote:
>>
>>> All chunks must be prefixed by a chunk length - even if that length is 
>>> zero.
>>>
>>> On Friday, 17 September 2021 at 16:53:07 UTC+1 dmo...@synack.com wrote:
>>>
>>>> Oh, thanks for clarifying that. But still, even if transfer encoding 
>>>> will be chunked, I don't see why it would make up a body of "0\r\n\r\n" if 
>>>> the nop body wouldn't give away any bytes at all.
>>>>
>>>> On Friday, September 17, 2021 at 7:56:21 AM UTC-3 seank...@gmail.com 
>>>> wrote:
>>>>
>>>>> This was an intentional change in 1.8 
>>>>> https://github.com/golang/go/issues/20257#issuecomment-299509391
>>>>>
>>>>> On Friday, September 17, 2021 at 6:45:13 AM UTC+2 dmo...@synack.com 
>>>>> wrote:
>>>>>
>>>>>> Hi, when using a custom io.ReadCloser nop as body with method POST, 
>>>>>> PUT, PATCH, TRACE or custom then (*http.Request).Write outputs a body of 
>>>>>> the form "0\r\n\r\n" (without the quotes). Proof-of-concept: 
>>>>>> https://play.golang.org/p/Rg2cZ0wihdd
>>>>>>
>>>>>> Besides the fix, I think it would be useful to have body checked if 
>>>>>> it satisfies interface{ Len() int } or something similar (this would 
>>>>>> simplify code too by removing several type assertions, e.g., 
>>>>>> isKnownInMemoryReader func in net/http/trans...@go1.17.1) so that we can 
>>>>>> avoid chunked transfer encoding.
>>>>>>
>>>>>> This email may contain material that is confidential for the sole use 
>>>>>> of the intended recipient(s).  Any review, reliance or distribution or 
>>>>>> disclosure by others without express permission is strictly prohibited.  
>>>>>> If 
>>>>>> you are not the intended recipient, please contact the sender and delete 
>>>>>> all copies of this message.
>>>>>>
>>>>> -- 
>>> You received this message because you are subscribed to a topic in the 
>>> Google Groups "golang-nuts" group.
>>> To unsubscribe from this topic, visit 
>>> https://groups.google.com/d/topic/golang-nuts/ZlhK8whGwck/unsubscribe.
>>> To unsubscribe from this group and all its topics, send an email to 
>>> golang-nuts...@googlegroups.com.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/golang-nuts/6847c965-3325-40f1-825e-2ccafa70cd3an%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/golang-nuts/6847c965-3325-40f1-825e-2ccafa70cd3an%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
>> This email may contain material that is confidential for the sole use of 
>> the intended recipient(s).  Any review, reliance or distribution or 
>> disclosure by others without express permission is strictly prohibited.  If 
>> you are not the intended recipient, please contact the sender and delete 
>> all copies of this message.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/859e6212-efd1-4cf0-9bc5-e33449534ed8n%40googlegroups.com.

Reply via email to