There is no Len() defined for io.Reader. That is the crux of the issue. You are defining it because you need it. It needs to be defined and documented by the api specification, otherwise it is an incorrect assumption and usage - aka brittle code.
> On Feb 6, 2019, at 9:05 AM, Burak Serdar <bser...@ieee.org> wrote: > >> On Wed, Feb 6, 2019 at 7:56 AM Robert Engels <reng...@ix.netcom.com> wrote: >> >> But is it really? If you read the description for Len() on bytes.Buffer it >> is the length of unread portion. But that doesn’t mean the buffer isn’t just >> a portion of the entire body - it can be a chunk which is continually >> reloaded. > > Reader.Len() should give how much you can read from the reader, so > for a buffer, it should return the unread portion. If you have a > reader that loads its chunks as needed and it knows the total length, > that interpretation of Len() is still correct. If you have a Reader > that doesn't know the length, then it should not implement Len(). > >> >> This is the danger in using private APIs publically based upon the existence >> of a method - it leads to very brittle code - and there are almost certainly >> better ways to design it to avoid these issues. If the core api is not >> expressive enough then it will be more difficult. > > Len() is not a private API, it has fairly well-understood and agreed > upon semantics, so I think for this case it is safe to use it without > much negative effect. The http.Request could use a redesign though. > >> >>>> On Feb 6, 2019, at 8:30 AM, Burak Serdar <bser...@ieee.org> wrote: >>>> >>>> On Wed, Feb 6, 2019 at 5:15 AM Robert Engels <reng...@ix.netcom.com> wrote: >>>> >>>> I see now, but if that can be the case, shouldn’t the Body be documented >>>> that the Reader may be a ReaderWithLen, and the consumer is free to type >>>> check/cast? If not, you are using internal details that you should not be. >>> >>> Yes, the documentation should say if the reader has a Len() method it >>> would be used to set the ContentLength. Len is no longer an internal >>> detail then. >>> >>>> >>>> This is a problem with Go in general. Because the returned object >>>> “implements” some interface because it happens to have the required >>>> method, doesn’t mean it was designed to be used that way, or that it has >>>> the required semantics - unless documented to have them. >>> >>> I agree with you there. Len() is straight forward, but in general just >>> because a function is named something doesn't mean it'll do the same >>> thing for all implementations. On the other end of the spectrum is >>> Java-like interfaces where you want explicit inheritance of a specific >>> interface. I don't know if there's anything in between, but I like >>> Go's approach much better. >>> >>>> >>>> On Feb 6, 2019, at 2:22 AM, Matteo Biagetti <matteo.biage...@gmail.com> >>>> wrote: >>>> >>>> Make sense, thanks for explanation >>>> >>>> >>>> >>>> Il giorno mercoledì 6 febbraio 2019 07:28:54 UTC+1, Burak Serdar ha >>>> scritto: >>>>> >>>>> On Tue, Feb 5, 2019 at 8:13 PM robert engels <ren...@ix.netcom.com> wrote: >>>>>> >>>>>> That’s what I was trying to point out. Your design is not correct. The >>>>>> Body is a Reader, not a Buffer - the length of the request/body may be >>>>>> indeterminate - that is, a stream. Attempting to get the length of an >>>>>> underlying buffer is not only probably not possible, but not correct in >>>>>> many situations. >>>>> >>>>> The length of the body *may* be indeterminate, and if that's the case, >>>>> the underlying Reader will not have a Len method. The design is to >>>>> handle the case where the underlying Reader is a Buffer with a Len >>>>> method. If the Reader has Len, then the NopCloser derived from that >>>>> will also have a Len, and NewRequest can set the content length. If >>>>> the Reader does not have Len, then the content length is unknown. >>>>> >>>>>> >>>>>> There is a reason the Body is a ReaderCloser and not a buffer. It is >>>>>> part of the http specification. >>>>>> >>>>>> On Feb 5, 2019, at 9:00 PM, Burak Serdar <bse...@ieee.org> wrote: >>>>>> >>>>>> On Tue, Feb 5, 2019 at 7:00 PM Robert Engels <ren...@ix.netcom.com> >>>>>> wrote: >>>>>> >>>>>> >>>>>> Shouldn’t you just be taking the content length from the header if >>>>>> forwarding the same body. There is no need for the length of the body. >>>>>> >>>>>> >>>>>> True. What I was suggesting is a fix for the general case. >>>>>> >>>>>> >>>>>> On Feb 5, 2019, at 6:53 PM, Burak Serdar <bse...@ieee.org> wrote: >>>>>> >>>>>> On Tue, Feb 5, 2019 at 5:18 PM Dan Kortschak <d...@kortschak.io> wrote: >>>>>> >>>>>> Personally, I think this is a bug in the behaviour of NewRequest. See h >>>>>> ttps://github.com/golang/go/issues/18117 for some additional context. >>>>>> >>>>>> >>>>>> Agreed. One solution could be to have: >>>>>> >>>>>> type HasLen interface { >>>>>> int Len() >>>>>> } >>>>>> >>>>>> Then have NopCloser return a nopCloser with len if the underlying >>>>>> implementation has len, with the obvious changes to NewRequest.Ugly, >>>>>> but can be done without API changes. >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Tue, 2019-02-05 at 05:18 -0800, matteo....@gmail.com wrote: >>>>>> I've the following situation: >>>>>> I proxy a request to another server and when I made a POST and create >>>>>> a new >>>>>> request, the contentLength is zero: >>>>>> >>>>>> req2, _ := http.NewRequest(req.Method, newApiUrl , req.Body) >>>>>> fmt.Println("New request from body:", req2.ContentLength) // >>>>>> print 0 >>>>>> >>>>>> Checking in the source code of the NewRequest func Body don't respect >>>>>> some >>>>>> interface and populate the ContentLength field. >>>>>> >>>>>> Could be a bug? Which could be a valid approach in order to create a >>>>>> new >>>>>> request from an existing one and correct set the Body length? >>>>>> >>>>>> A working example here: >>>>>> >>>>>> https://play.golang.org/p/SvCDLj0NrXb >>>>>> >>>>>> Thanks! >>>>>> >>>>>> >>>>>> -- >>>>>> 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...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>>> >>>>>> -- >>>>>> 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...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>>> >>>>>> -- >>>>>> 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...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>>> >>>>>> -- >>>>>> 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...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>>> >>>> >>>> -- >>>> 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. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>>> -- >>>> 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. >>>> For more options, visit https://groups.google.com/d/optout. >> >> -- >> 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. >> For more options, visit https://groups.google.com/d/optout. -- 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. For more options, visit https://groups.google.com/d/optout.