-
Notifications
You must be signed in to change notification settings - Fork 322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wsgi response header handling disregards RFC7230 with regard to an HTTP 204 response code #746
Labels
Comments
Thank you, I'll fix it. |
@temoto Much appreciated! Thanks! |
temoto
added a commit
that referenced
this issue
Jan 13, 2022
… response with a status code of 1xx, 204 or (2xx to CONNECT request) https://httpwg.org/specs/rfc7230.html#rfc.section.3.3.1 #746
openstack-mirroring
pushed a commit
to openstack/ironic-inspector
that referenced
this issue
Jan 14, 2022
It turns out that eventlet has been injecting a ``Transfer-Encoding`` header as of recent into WSGI application response headers. The result of this ultimately depends on how the HTTP client which is passing the request to the server is written to handle data. Apache, for example, will return that an invalid response was received. In part because it sees the request end, with an HTTP 204 response code, but also an encoding indicating there is a multipart body encoding inbound. Which is confusing. Other C based HTTP clients can have any number of reactions up to and including disconnecting sessions. Curl, depending on the headers present either returns success but notes body weirdness or actually returns return code 18. Python-Requests kind of has it a little worse, and we see this with clients. With it, it tries to prepare a respones content body based upon the presence of the header indicating there is a body. But it blows up thinking there is more data to read on the socket when there is not more data to read. Regardless, all of this is an RFC7230 violation. Neither Content-Length nor Transfer-Encoding should be on an HTTP 204 response. However, Content-Length is the lesser evil, and we have a similar endpoing in Ironic which *does* explicitly get returned with a zero length content-length, and does not demonstrate such issues. As such, in the interest of the lesser evils until Eventlet's evil ways of header injection are remedied, we're explicitly going to force a Content-Length header to be sent indicating a zero length response. For more information, please see: eventlet/eventlet#746 Change-Id: I014cc65c79222f4d4d7c2b6ff11a76e56659340c
openstack-mirroring
pushed a commit
to openstack/openstack
that referenced
this issue
Jan 14, 2022
* Update ironic-inspector from branch 'master' to 55e47c630beb99f880045113e4f86bc1817b50da - Return a content-length on HTTP204 to prevent client failures It turns out that eventlet has been injecting a ``Transfer-Encoding`` header as of recent into WSGI application response headers. The result of this ultimately depends on how the HTTP client which is passing the request to the server is written to handle data. Apache, for example, will return that an invalid response was received. In part because it sees the request end, with an HTTP 204 response code, but also an encoding indicating there is a multipart body encoding inbound. Which is confusing. Other C based HTTP clients can have any number of reactions up to and including disconnecting sessions. Curl, depending on the headers present either returns success but notes body weirdness or actually returns return code 18. Python-Requests kind of has it a little worse, and we see this with clients. With it, it tries to prepare a respones content body based upon the presence of the header indicating there is a body. But it blows up thinking there is more data to read on the socket when there is not more data to read. Regardless, all of this is an RFC7230 violation. Neither Content-Length nor Transfer-Encoding should be on an HTTP 204 response. However, Content-Length is the lesser evil, and we have a similar endpoing in Ironic which *does* explicitly get returned with a zero length content-length, and does not demonstrate such issues. As such, in the interest of the lesser evils until Eventlet's evil ways of header injection are remedied, we're explicitly going to force a Content-Length header to be sent indicating a zero length response. For more information, please see: eventlet/eventlet#746 Change-Id: I014cc65c79222f4d4d7c2b6ff11a76e56659340c
openstack-mirroring
pushed a commit
to openstack/ironic-inspector
that referenced
this issue
Jan 17, 2022
It turns out that eventlet has been injecting a ``Transfer-Encoding`` header as of recent into WSGI application response headers. The result of this ultimately depends on how the HTTP client which is passing the request to the server is written to handle data. Apache, for example, will return that an invalid response was received. In part because it sees the request end, with an HTTP 204 response code, but also an encoding indicating there is a multipart body encoding inbound. Which is confusing. Other C based HTTP clients can have any number of reactions up to and including disconnecting sessions. Curl, depending on the headers present either returns success but notes body weirdness or actually returns return code 18. Python-Requests kind of has it a little worse, and we see this with clients. With it, it tries to prepare a respones content body based upon the presence of the header indicating there is a body. But it blows up thinking there is more data to read on the socket when there is not more data to read. Regardless, all of this is an RFC7230 violation. Neither Content-Length nor Transfer-Encoding should be on an HTTP 204 response. However, Content-Length is the lesser evil, and we have a similar endpoing in Ironic which *does* explicitly get returned with a zero length content-length, and does not demonstrate such issues. As such, in the interest of the lesser evils until Eventlet's evil ways of header injection are remedied, we're explicitly going to force a Content-Length header to be sent indicating a zero length response. For more information, please see: eventlet/eventlet#746 Change-Id: I014cc65c79222f4d4d7c2b6ff11a76e56659340c (cherry picked from commit 55e47c6)
openstack-mirroring
pushed a commit
to openstack/ironic-inspector
that referenced
this issue
Jan 17, 2022
It turns out that eventlet has been injecting a ``Transfer-Encoding`` header as of recent into WSGI application response headers. The result of this ultimately depends on how the HTTP client which is passing the request to the server is written to handle data. Apache, for example, will return that an invalid response was received. In part because it sees the request end, with an HTTP 204 response code, but also an encoding indicating there is a multipart body encoding inbound. Which is confusing. Other C based HTTP clients can have any number of reactions up to and including disconnecting sessions. Curl, depending on the headers present either returns success but notes body weirdness or actually returns return code 18. Python-Requests kind of has it a little worse, and we see this with clients. With it, it tries to prepare a respones content body based upon the presence of the header indicating there is a body. But it blows up thinking there is more data to read on the socket when there is not more data to read. Regardless, all of this is an RFC7230 violation. Neither Content-Length nor Transfer-Encoding should be on an HTTP 204 response. However, Content-Length is the lesser evil, and we have a similar endpoing in Ironic which *does* explicitly get returned with a zero length content-length, and does not demonstrate such issues. As such, in the interest of the lesser evils until Eventlet's evil ways of header injection are remedied, we're explicitly going to force a Content-Length header to be sent indicating a zero length response. For more information, please see: eventlet/eventlet#746 Change-Id: I014cc65c79222f4d4d7c2b6ff11a76e56659340c (cherry picked from commit 55e47c6)
openstack-mirroring
pushed a commit
to openstack/ironic-inspector
that referenced
this issue
Jan 17, 2022
It turns out that eventlet has been injecting a ``Transfer-Encoding`` header as of recent into WSGI application response headers. The result of this ultimately depends on how the HTTP client which is passing the request to the server is written to handle data. Apache, for example, will return that an invalid response was received. In part because it sees the request end, with an HTTP 204 response code, but also an encoding indicating there is a multipart body encoding inbound. Which is confusing. Other C based HTTP clients can have any number of reactions up to and including disconnecting sessions. Curl, depending on the headers present either returns success but notes body weirdness or actually returns return code 18. Python-Requests kind of has it a little worse, and we see this with clients. With it, it tries to prepare a respones content body based upon the presence of the header indicating there is a body. But it blows up thinking there is more data to read on the socket when there is not more data to read. Regardless, all of this is an RFC7230 violation. Neither Content-Length nor Transfer-Encoding should be on an HTTP 204 response. However, Content-Length is the lesser evil, and we have a similar endpoing in Ironic which *does* explicitly get returned with a zero length content-length, and does not demonstrate such issues. As such, in the interest of the lesser evils until Eventlet's evil ways of header injection are remedied, we're explicitly going to force a Content-Length header to be sent indicating a zero length response. For more information, please see: eventlet/eventlet#746 Change-Id: I014cc65c79222f4d4d7c2b6ff11a76e56659340c (cherry picked from commit 55e47c6)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
RFC7230 specifies that transfer encoding must not include a Transfer-Encoding header in an HTTP 204 response. However, eventlet appears to always do so by default based upon the class of request, and if the response does not have a content-length field explicitly defined. Then regardless of the response code, it is stamping the reply with a Transfer-Encoding header.
Specifically, as noted, it is basing it's response on the presence of a Content-Length header. However, HTTP 204 responses must not have a Content-Length header based upon the RFC.
This creates a situation where, as previously mentioned the Transfer-Encoding header is injected, and a HTTP/1.1 client can find itself confused, and actually issue an error or exception as a result of the response because a client interpreting the Transfer-Encoding before the result code is expecting more data. That data, however, will never come and depending on the application, the socket may close as well, ultimately generating additional errors.
@dtantsur was kind enough to whip up a reproducer utilizing Flask and eventlet wsgi:
Test and result:
Curl doesn't return a non-zero return code in this precise reproducer case, but you can see that the header is injected inappropriately when compared to RFC7230. This has varying effects on different client implementations. In one case we encountered this was aiding in Apache httpd returning a incomplete response error to the end client. In another we found python-requests trying to parse the response body and an exception being raised as a result there.
This was observed on Eventlet 0.30.2 and comparing the code to the present development branch indicates it is still present.
Both encountered on Python 3.8.5 and Python 3.6.8. Debian and Red Hat Enterprise Linux, respectively.
Ideally, the injection of headers would be skipped if the HTTP result code is 204.
The text was updated successfully, but these errors were encountered: