Skip to content
This repository has been archived by the owner on Dec 8, 2017. It is now read-only.

Ensure the request body buffer is not exhausted #4

Merged
merged 1 commit into from
Oct 9, 2015

Conversation

mbland
Copy link
Contributor

@mbland mbland commented Oct 9, 2015

Was notified of the issue when @dlapiduz pinged me about POST requests
to https://tock.18f.gov/ resulting in 500s. Digging in the oauth2_proxy logs,
I noticed messages like this appearing before every 500:

2015/10/09 16:08:15 reverseproxy.go:184: http: proxy error: http: ContentLength=128 with Body length 0

Searching for that error string turned up:

https://stackoverflow.com/questions/23070876/reading-body-of-http-request-without-modifying-request-state

The issue was that reading from http.Request.Body to generate the request
signature was exhausting the io.ReadCloser. The solution was to read the
entire body into a new buffer, wrap that buffer in an ioutil.NopCloser and
assign it back to http.Request.Body, and then use that same buffer to
compute the signature.

The new assert statement in TestRequestSignaturePost reproduced the original
bug and verified the fix.

cc: @jcscottiii

Was notified of the issue when @dlapiduz pinged me about POST requests
to https://tock.18f.gov/ resulting in 500s. Digging in the oauth2_proxy logs,
I noticed messages like this appearing before every 500:

```
2015/10/09 16:08:15 reverseproxy.go:184: http: proxy error: http: ContentLength=128 with Body length 0
```

Searching for that error string turned up:

https://stackoverflow.com/questions/23070876/reading-body-of-http-request-without-modifying-request-state

The issue was that reading from `http.Request.Body` to generate the request
signature was exhausting the `io.ReadCloser`. The solution was to read the
entire body into a new buffer, wrap that buffer in an `ioutil.NopCloser` and
assign it back to `http.Request.Body`, and then use that same buffer to
compute the signature.

The new assert statement in `TestRequestSignaturePost` reproduced the original
bug and verified the fix.
jcscottiii added a commit that referenced this pull request Oct 9, 2015
Ensure the request body buffer is not exhausted
@jcscottiii jcscottiii merged commit 4ce5f9a into master Oct 9, 2015
@mbland mbland deleted the fix-post-req-bug branch October 9, 2015 23:18
mbland pushed a commit to cloud-gov/oauth2_proxy that referenced this pull request Oct 10, 2015
Using fakeNetConn in the test exposes a bug in 18F/hmacauth when handling POST
requests, addressed by 18F/hmacauth#4. The bug was that the strings.Reader
does not consume its buffer contents the same way that a net.Conn does. So the
test would pass because its request body would still be intact after signing,
but during live testing, the request body would be consumed by
HmacAuth.requestSignature().

It also happened to expose a subsequent 18F/hmacauth bug addressed in
18F/hmacauth#5. It turns out that checking Request.ContentLength is an
unreliable way of detecting that a body is present, and checking body != nil
is sufficient.

18F/hmacauth#4 is already merged; when 18F/hmacauth#5 is in, I'll tag
18F/hmacauth v1.0.1 and update the Godeps to use that version, at which point
the test should pass.
mbland pushed a commit to cloud-gov/oauth2_proxy that referenced this pull request Oct 13, 2015
v1.0.1 contains 18F/hmacauth#4 and 18F/hmacauth#5, needed to make
TestRequestSignaturePostRequest pass again.
mbland pushed a commit to cloud-gov/oauth2_proxy that referenced this pull request Nov 9, 2015
Using fakeNetConn in the test exposes a bug in 18F/hmacauth when handling POST
requests, addressed by 18F/hmacauth#4. The bug was that the strings.Reader
does not consume its buffer contents the same way that a net.Conn does. So the
test would pass because its request body would still be intact after signing,
but during live testing, the request body would be consumed by
HmacAuth.requestSignature().

It also happened to expose a subsequent 18F/hmacauth bug addressed in
18F/hmacauth#5. It turns out that checking Request.ContentLength is an
unreliable way of detecting that a body is present, and checking body != nil
is sufficient.

18F/hmacauth#4 is already merged; when 18F/hmacauth#5 is in, I'll tag
18F/hmacauth v1.0.1 and update the Godeps to use that version, at which point
the test should pass.
mbland pushed a commit to cloud-gov/oauth2_proxy that referenced this pull request Nov 9, 2015
v1.0.1 contains 18F/hmacauth#4 and 18F/hmacauth#5, needed to make
TestRequestSignaturePostRequest pass again.
mbland pushed a commit to cloud-gov/oauth2_proxy that referenced this pull request Nov 9, 2015
Using fakeNetConn in the test exposes a bug in 18F/hmacauth when handling POST
requests, addressed by 18F/hmacauth#4. The bug was that the strings.Reader
does not consume its buffer contents the same way that a net.Conn does. So the
test would pass because its request body would still be intact after signing,
but during live testing, the request body would be consumed by
HmacAuth.requestSignature().

It also happened to expose a subsequent 18F/hmacauth bug addressed in
18F/hmacauth#5. It turns out that checking Request.ContentLength is an
unreliable way of detecting that a body is present, and checking body != nil
is sufficient.

18F/hmacauth#4 is already merged; when 18F/hmacauth#5 is in, I'll tag
18F/hmacauth v1.0.1 and update the Godeps to use that version, at which point
the test should pass.
mbland pushed a commit to cloud-gov/oauth2_proxy that referenced this pull request Nov 9, 2015
v1.0.1 contains 18F/hmacauth#4 and 18F/hmacauth#5, needed to make
TestRequestSignaturePostRequest pass again.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants