I agree that this is a brittle API and it's one that has bitten us twice (partly because - I beleive - the dev_appserver.py development server is broken in how it deals with the cases here. This is why I filed an issue - though not with great hope of a fix other than maybe improving the documentation.
On Thu, 2019-02-07 at 16:10 -0600, robert engels wrote: > So GetBody just fails… It returns NoBody in this case.. which means > calling code will just break (when the original request is not one of > the known types). > > So, according to the referenced issue, 307/308 redirects won’t work > when the underlying request is not a known type. > > This is a very brittle API IMO. If you need to do stuff like this, > the readers should be using mark/reset etc with buffered streams, not > relying on special cased functions like GetBody that don’t work in > all cases. > > > > > On Feb 7, 2019, at 3:42 PM, Dan Kortschak <d...@kortschak.io> wrote: > > > > Keeping a zeroed state is important for the GetBody func because > > the > > io.ReadCloser returned by GetBody can be read and closed. If there > > is > > no zero state for the next time GetBody is called, it is not > > idempotent. This would break the whole point of it existing. > > > > See https://go-review.googlesource.com/c/go/+/31733/ > > > > On Thu, 2019-02-07 at 15:33 -0600, robert engels wrote: > > > > > > I agree with you on the correct solution - vs. the OP’s request > > > of > > > the GetWrappedXXXX method. > > > > > > I guess I still don’t understand the “zeroed” concern though. If > > > you > > > adhere to the “don’t mutate values…” then why do the zero copy at > > > all > > > ? The state of the body should still be the state it was passed > > > in as > > > (unless the caller was breaking the aforementioned rule anyway…). > > > > > > Having “blessed types” is not a good design IMO - better to just > > > declare the required interfaces and use those - especially when > > > the > > > object being provided as a parameter is already an interface… > > > just > > > seems lazy… (and long-term error prone). > > > > > > > > > > > > > > > > > > > > > On Feb 7, 2019, at 3:05 PM, Dan Kortschak <d...@kortschak.io> > > > > wrote: > > > > > > > > Their is an assumption in the code that users don't mutate > > > > values > > > > under > > > > the feet of routines that have been called. The copy does not > > > > protect > > > > against that and is not designed for that purpose; it is there > > > > to > > > > make > > > > the GetBody function return a zeroed copy of the body (for some > > > > definition of zeroed - zero is the state that was handed in to > > > > the > > > > NewRequest call). If the behaviour of the copy here is broken, > > > > any > > > > Go > > > > code that causes a slice, map or pointer to be retained is > > > > broken > > > > since > > > > the user can mutate the backing data after the call has done > > > > work > > > > on > > > > it. This becomes a philosophical point. > > > > > > > > There is a simple work around (not as simple as having > > > > NewRequest > > > > Just > > > > Do The Right Thing™, but reasonable) that does not require > > > > reflect > > > > and > > > > puts the control in the users' hands. Since the ContentLength > > > > and > > > > GetBody fields are exported, they can be set after the return > > > > of > > > > NewRequest in the same way that NewRequest does for the blessed > > > > types, > > > > but with the users' knowledge of internal behaviours of their > > > > types. > > > > > > > > An example of this is here https://bitbucket.org/ausocean/iot/p > > > > ull- > > > > requ > > > > ests/42 > > > > > > > > On Thu, 2019-02-07 at 14:55 -0600, robert engels wrote: > > > > > > > > > > > > > > > I see the documented use of the types in NewRequest - you are > > > > > correct > > > > > - I was wrong. > > > > > > > > > > But, it could of easily also declared that if the provided > > > > > Reader > > > > > is > > > > > also a Lener, it uses it to determine the content length. Why > > > > > have > > > > > this behavior for Closer and not for Lener? Then you don’t > > > > > need > > > > > the > > > > > type switch. You say, well the copy... > > > > > > > > > > The current code with the copy is broken - the caller could > > > > > continue > > > > > to modify the contents of the bytes.Buffer and things would > > > > > not > > > > > work > > > > > as expected since the backing array of the slice is shared - > > > > > so > > > > > how > > > > > is the copy helping ? The length will remain the same, but > > > > > the > > > > > data > > > > > represented could be corrupted. > > > > > > > > > > The correct solution is to declare that NewRequest takes an > > > > > interface > > > > > Content, that has both Reader and ContentLength methods, > > > > > where > > > > > ContentLength() can return -1 if the content length is > > > > > indeterminate. > > > > > Then declare simple facades for Content from bytes.Buffer, a > > > > > string, > > > > > etc. And also declare that continued use of the Content after > > > > > NewRequest is undefined. And if you wanted to retain the > > > > > simplicity, > > > > > just declare it uses ContentLength like it uses Closer. > > > > > > > > > > I am all for the simplicity of Go, but “solutions" like > > > > > NewRequest > > > > > are not the way modern software should be developed. Casting > > > > > an > > > > > interface to a concrete type is a sign of code that needs > > > > > design > > > > > work. Having to read the doc in addition to the method > > > > > signature > > > > > is > > > > > also a sign the interface needs work (primarily since changes > > > > > to > > > > > the > > > > > doc can/will/might change behavior but it avoids compile time > > > > > type > > > > > checking = brittle code with obscure bugs). > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Feb 7, 2019, at 1:56 PM, Dan Kortschak <d...@kortschak.io > > > > > > > > > > > > > wrote: > > > > > > > > > > > > I didn't mention the word internal, nor did I imply it; > > > > > > with > > > > > > documentation stating that it would be used, it is clearly > > > > > > *not* > > > > > > internal. > > > > > > > > > > > > If you look at the code in question, you can see a probable > > > > > > reason > > > > > > why > > > > > > a Lener interface is not used; for each of the blessed > > > > > > types, a > > > > > > concrete copy of the pointed-to-value is made to allow > > > > > > GetBody > > > > > > to > > > > > > return it. This cannot be done with an interface value > > > > > > without > > > > > > the > > > > > > use > > > > > > of reflect. > > > > > > > > > > > > Please show me a Len method in the standard library that > > > > > > does > > > > > > not > > > > > > return the number of available-to-access elements in a > > > > > > collection. > > > > > > > > > > > > > > > > > > On Thu, 2019-02-07 at 13:27 -0600, robert engels wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > I am not following. You stated that the usage of Len was > > > > > > > internal > > > > > > > and > > > > > > > a type switch on known concrete types, so how is related > > > > > > > to > > > > > > > how > > > > > > > the > > > > > > > OP was attempting to have things work? > > > > > > > > > > > > > > There is no “generally accepted use of Len()”, otherwise > > > > > > > it > > > > > > > would > > > > > > > not > > > > > > > need to perform a type switch on known concrete types - > > > > > > > it > > > > > > > would > > > > > > > cast > > > > > > > to an interface declaring Len(), and use the interface, > > > > > > > and > > > > > > > then > > > > > > > it > > > > > > > would work with any type. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Feb 7, 2019, at 1:07 PM, Dan Kortschak <dan@kortscha > > > > > > > > k.io > > > > > > > > > > > > > > > > > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > Yeah, I'm not agreeing with you. > > > > > > > > > > > > > > > > On Thu, 2019-02-07 at 07:07 -0600, Robert Engels wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > You are agreeing with me. A type switch on concrete > > > > > > > > > types > > > > > > > > > (that > > > > > > > > > you > > > > > > > > > control) is far different than using an available > > > > > > > > > Len() > > > > > > > > > method > > > > > > > > > and > > > > > > > > > assuming the same semantics. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Feb 7, 2019, at 1:05 AM, Dan Kortschak <dan@kort > > > > > > > > > > scha > > > > > > > > > > k.io > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > Addressing the first sentence, it was a direct > > > > > > > > > > answer > > > > > > > > > > to a > > > > > > > > > > comment > > > > > > > > > > you > > > > > > > > > > made: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 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. > > > > > > > > > > As far as the claim that there is a need to have a > > > > > > > > > > Len > > > > > > > > > > method > > > > > > > > > > in > > > > > > > > > > io.Reader, have a look at the code in question. It > > > > > > > > > > type > > > > > > > > > > asserts > > > > > > > > > > on > > > > > > > > > > three concrete types that are known to the > > > > > > > > > > function, > > > > > > > > > > all > > > > > > > > > > three > > > > > > > > > > have > > > > > > > > > > a > > > > > > > > > > Len method and this is used to obtain the known > > > > > > > > > > length. > > > > > > > > > > All > > > > > > > > > > other > > > > > > > > > > io.Readers are considered to have an unknown > > > > > > > > > > length. > > > > > > > > > > > > > > > > > > > > Whether it's wrong to use Len depends on whether > > > > > > > > > > there > > > > > > > > > > is a > > > > > > > > > > generally > > > > > > > > > > accepted and consistent set of semantics to Len() > > > > > > > > > > int. > > > > > > > > > > There > > > > > > > > > > is. > > > > > > > > > > This > > > > > > > > > > is strengthened if the use of an existing Len > > > > > > > > > > method is > > > > > > > > > > noted > > > > > > > > > > in > > > > > > > > > > the > > > > > > > > > > docs. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Wed, 2019-02-06 at 15:50 -0600, robert engels > > > > > > > > > > > wrote: > > > > > > > > > > > I am not sure what that has to do with the > > > > > > > > > > > discussion. My > > > > > > > > > > > point > > > > > > > > > > > was > > > > > > > > > > > that for it to be applicable here, it needs to be > > > > > > > > > > > defined > > > > > > > > > > > as > > > > > > > > > > > part > > > > > > > > > > > of > > > > > > > > > > > io.Reader, since that is what Body is declared > > > > > > > > > > > as. It > > > > > > > > > > > is > > > > > > > > > > > not, > > > > > > > > > > > so > > > > > > > > > > > using in the manner outlined is not correct IMO. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Feb 6, 2019, at 3:37 PM, Dan Kortschak <dan@ > > > > > > > > > > > > kort > > > > > > > > > > > > scha > > > > > > > > > > > > k.io > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > The generalised semantics of Len are that it > > > > > > > > > > > > returns > > > > > > > > > > > > the > > > > > > > > > > > > number > > > > > > > > > > > > of > > > > > > > > > > > > available elements in the collection, being a > > > > > > > > > > > > cognate > > > > > > > > > > > > of > > > > > > > > > > > > the > > > > > > > > > > > > len > > > > > > > > > > > > built- > > > > > > > > > > > > in. This means that as you consume elements > > > > > > > > > > > > from a > > > > > > > > > > > > buffer, > > > > > > > > > > > > the > > > > > > > > > > > > Len > > > > > > > > > > > > value reduces. This is directly equivalent to > > > > > > > > > > > > > > > > > > > > > > > > for len(buf) != 0 { > > > > > > > > > > > > println(buf[0]) > > > > > > > > > > > > buf = buf[1:] > > > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Wed, 2019-02-06 at 08:56 -0600, Robert > > > > > > > > > > > > > Engels > > > > > > > > > > > > > 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. > > > > > > > > > > > > > > > > > > > > > > > > > > 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. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Feb 6, 2019, at 8:30 AM, Burak Serdar > > > > > > > > > > > > > > <bserd > > > > > > > > > > > > > > ar@i > > > > > > > > > > > > > > eee. > > > > > > > > > > > > > > org> > > > > > > > > > > > > > > wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > On Wed, Feb 6, 2019 at 5:15 AM Robert > > > > > > > > > > > > > > > Engels > > > > > > > > > > > > > > > <rengels > > > > > > > > > > > > > > > @ix. > > > > > > > > > > > > > > > netc > > > > > > > > > > > > > > > om.c > > > > > > > > > > > > > > > om> 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.biagetti@ > > > > > > > > > > > > > > > gmai > > > > > > > > > > > > > > > l.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 > > > > > > > > > > > > > > > > .net > > > > > > > > > > > > > > > > com. > > > > > > > > > > > > > > > > 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.n > > > > > > > > > > > > > > > > > etco > > > > > > > > > > > > > > > > > m.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.. > > > > > > > > > > > > > > > > > .@ko > > > > > > > > > > > > > > > > > rtsc > > > > > > > > > > > > > > > > > hak. > > > > > > > > > > > > > > > > > io> wrote: > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Personally, I think this is a bug in > > > > > > > > > > > > > > > > > the > > > > > > > > > > > > > > > > > behaviour of > > > > > > > > > > > > > > > > > NewRequest. See h > > > > > > > > > > > > > > > > > ttps://github.com/golang/go/issues/18 > > > > > > > > > > > > > > > > > 117 > > > > > > > > > > > > > > > > > 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.... > > > > > > > > > > > > > > > > > @gma > > > > > > > > > > > > > > > > > il.c > > > > > > > > > > > > > > > > > om > > > > > > > > > > > > > > > > > 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...@g > > > > > > > > > > > > > > > > > oogl > > > > > > > > > > > > > > > > > egro > > > > > > > > > > > > > > > > > ups. > > > > > > > > > > > > > > > > > com. > > > > > > > > > > > > > > > > > For more options, visit https://group > > > > > > > > > > > > > > > > > s.go > > > > > > > > > > > > > > > > > ogle > > > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > > > /d/o > > > > > > > > > > > > > > > > > ptou > > > > > > > > > > > > > > > > > t. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > > > 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...@g > > > > > > > > > > > > > > > > > oogl > > > > > > > > > > > > > > > > > egro > > > > > > > > > > > > > > > > > ups. > > > > > > > > > > > > > > > > > com. > > > > > > > > > > > > > > > > > For more options, visit https://group > > > > > > > > > > > > > > > > > s.go > > > > > > > > > > > > > > > > > ogle > > > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > > > /d/o > > > > > > > > > > > > > > > > > ptou > > > > > > > > > > > > > > > > > t. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > > > 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...@g > > > > > > > > > > > > > > > > > oogl > > > > > > > > > > > > > > > > > egro > > > > > > > > > > > > > > > > > ups. > > > > > > > > > > > > > > > > > com. > > > > > > > > > > > > > > > > > For more options, visit https://group > > > > > > > > > > > > > > > > > s.go > > > > > > > > > > > > > > > > > ogle > > > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > > > /d/o > > > > > > > > > > > > > > > > > ptou > > > > > > > > > > > > > > > > > t. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > > > 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...@g > > > > > > > > > > > > > > > > > oogl > > > > > > > > > > > > > > > > > egro > > > > > > > > > > > > > > > > > ups. > > > > > > > > > > > > > > > > > com. > > > > > > > > > > > > > > > > > For more options, visit https://group > > > > > > > > > > > > > > > > > s.go > > > > > > > > > > > > > > > > > ogle > > > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > > > /d/o > > > > > > > > > > > > > > > > > ptou > > > > > > > > > > > > > > > > > t. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > 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+unsubscribe@ > > > > > > > > > > > > > > > goog > > > > > > > > > > > > > > > legr > > > > > > > > > > > > > > > oups > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > . > > > > > > > > > > > > > > > For more options, visit https://groups.go > > > > > > > > > > > > > > > ogle > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > /d/o > > > > > > > > > > > > > > > ptou > > > > > > > > > > > > > > > t. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > > > > > > > > > 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+unsubscribe@ > > > > > > > > > > > > > > > goog > > > > > > > > > > > > > > > legr > > > > > > > > > > > > > > > oups > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > . > > > > > > > > > > > > > > > For more options, visit https://groups.go > > > > > > > > > > > > > > > ogle > > > > > > > > > > > > > > > .com > > > > > > > > > > > > > > > /d/o > > > > > > > > > > > > > > > ptou > > > > > > > > > > > > > > > t. -- 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.