-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Handle HTTP Response with no content-length header #3254
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
Conversation
I ran into an issue with a Google Rest API which did not send back a content-length header or a transfer-encoding header. If this happens the HTTPClient gives the user no access to the response body in any way. So my solution is to set the _size variable to the remaining length of data available on _client which makes sense and works perfectly for me now.
This PR is not OK in my opinion: available() just returns the number of bytes currently in the buffer, not the size of the payload. I think this coincidentally only goes right if the total data size send (headers + payload) is less than one tcp fragment length. |
I agree with @Jeroen88 here. this will only work if the whole response in in one packet. |
We need some sort of solution for this. What would be your suggestion? How do we deal with a response with no content-length? There has to be a way to handle this. |
There was quite some discussion about this at the esp8266. The conclusion is: either a server should send a Content-Length or it should send a Transfer-Encoding: chunked and the size of each chunk as a header of every chunk. No length and no encoding does not adhere to the standards and thus is not supported. If you really need it, you could wait for the timeout and read the response anyway. Maybe you have to do some small changes in the library. Or stick to the solution you found if you are sure that your payload is less than one frame. But do not send a PR for these solutions, because both are non-standard non generic. |
100% agree that this response is not following standard protocol and thus is invalid. Oddly enough though this response is coming from Google Cloud Services which is very strange it does not follow the http response outlined protocol. I validated that the response indeed does not have transfer-encoding or content-length headers by printing the full received packet out inside the sendRequest function just prior to the call to handleHeaderResponse. Here is the modified sendRequest function simply for diagnostic purposes:
Here is the printout of the received response:
I'm not crazy right? Google is not following standard protocols on responses? |
There is no requirement for the response to have a "Content-Length" header in HTTP 1.1 (ref) unless it is for backward compatibility to HTTP 1.0. Since the HTTPClient is likely sending an HTTP/1.1 GET request the server assumes it can send back the payload without the length since it is closing the connection after the payload. Can you test with HTTP/1.0 and see if it returns a Content-Length? |
@atanisoft
Still no content-length or transfer-encoding headers. That said oddly enough if I send the request using Post Man there is a transfer-encoding header which is set to chunked. I have validated I am sending all the same headers to the same endpoint with the same body. The only difference I can see is Post man had an additional header like this: |
For reference here is documentation on the endpoint I am sending the request to: |
That is odd that it doesn't return a Content-Length when there is a payload, but it doesn't technically violate the RFCs. Did you check the request headers as well? Likely the only option will be to read until there is no data left to read (ie: available() returns zero or connection closed). |
@atanisoft, |
@telliottosceola Can you share the headers sent by PostMan and by HTTPClient? I suspect there is a different in the request headers themselves which is leading to this inconsistent behavior in the response. |
@telliottosceola I think you are not crazy ;) @atanisoft I think it does violate what is stated in paragraph 4.4:
I may think that this line could be changed to make this use case work. If not chunked and no content length is available then asume the content is complete, else return the error. Agree? @telliottosceola Could you test this and if it works make a PR for it |
@Jeroen88 In the case of HTTP/1.1 "Connection: close" is present in the response headers so it is fine to not have the "Content-Length" header present. In the case of HTTP/1.0 though it is not returned but it is sent as part of the request as close (ref). As for your proposed fix, I'm not sure it will do what is expected. The problem is that without a known length of the response it will be required to read until end of stream. |
Agree, but the close header is also not sent in this case
Again agree with the second part, but reading the first reference you gave:
I think this is what the client will do with the change: instead of reporting a lost connections, it regards the content received as complete. |
The RFC is more inline with the Request not the Response. The Server can (and will) do whatever it wants after it sends the last byte of the Response. It is then up to the client side to determine what the behavior is.
The Request would have sent a Connection header (though it may have been keep-alive), but the Server did send "Connection: close" in the Response. In this case the client should read until there is no data and close the connection as normal and not attempt to reuse it. I don't know that the current code is parsing the response headers and checking for this scenario today. |
Here's the "code" output from postman(Sensitive information removed):
Postman response headers:
Postman response Body:
Status was 200. I have no idea why postman is getting the Transfer-Encoding header but the HTTP Client is not. I'll work on getting the raw request from HTTP Client, it appears to send headers and then the payload so give me a minute on that. |
Headers sent by HTTPClient:
I purposely added only one header: I'm going to attempt removing Content-Length from the request headers since that is not included in the Postman request. Just curious at this point. I'll also added Cache-Control just to be thorough. |
|
Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward? This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
👋 Hello telliottosceola, we appreciate your contribution to this project! Click to see more instructions ...
Review and merge process you can expect ...
|
I ran into an issue with a Google Rest API which did not send back a content-length header or a transfer-encoding header. If this happens the HTTPClient gives the user no access to the response body in any way. So my solution is to set the _size variable to the remaining length of data available on _client which makes sense and works perfectly for me now.