mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:17:34 +00:00
LibHTTP: Use 'close' as the default value for Connection in HTTP/1.0
Unlike HTTP/1.1 and above, the default behaviour for HTTP/1.0 servers is to close the connection after sending the response.
This commit is contained in:
parent
66bde66f49
commit
7578039188
2 changed files with 14 additions and 2 deletions
|
@ -5,6 +5,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/CharacterTypes.h>
|
||||||
#include <AK/Debug.h>
|
#include <AK/Debug.h>
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
#include <LibCompress/Brotli.h>
|
#include <LibCompress/Brotli.h>
|
||||||
|
@ -277,6 +278,15 @@ void Job::on_socket_connected()
|
||||||
dbgln("Job: Expected 2-part or 3-part HTTP status line, got '{}'", line);
|
dbgln("Job: Expected 2-part or 3-part HTTP status line, got '{}'", line);
|
||||||
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
|
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parts[0].matches("HTTP/?.?"sv, CaseSensitivity::CaseSensitive) || !is_ascii_digit(parts[0][5]) || !is_ascii_digit(parts[0][7])) {
|
||||||
|
dbgln("Job: Expected HTTP-Version to be of the form 'HTTP/X.Y', got '{}'", parts[0]);
|
||||||
|
return deferred_invoke([this] { did_fail(Core::NetworkJob::Error::ProtocolFailed); });
|
||||||
|
}
|
||||||
|
auto http_major_version = parse_ascii_digit(parts[0][5]);
|
||||||
|
auto http_minor_version = parse_ascii_digit(parts[0][7]);
|
||||||
|
m_legacy_connection = http_major_version < 1 || (http_major_version == 1 && http_minor_version == 0);
|
||||||
|
|
||||||
auto code = parts[1].to_uint();
|
auto code = parts[1].to_uint();
|
||||||
if (!code.has_value()) {
|
if (!code.has_value()) {
|
||||||
dbgln("Job: Expected numeric HTTP status");
|
dbgln("Job: Expected numeric HTTP status");
|
||||||
|
@ -641,8 +651,9 @@ void Job::finish_up()
|
||||||
auto response = HttpResponse::create(m_code, move(m_headers), m_received_size);
|
auto response = HttpResponse::create(m_code, move(m_headers), m_received_size);
|
||||||
deferred_invoke([this, response = move(response)] {
|
deferred_invoke([this, response = move(response)] {
|
||||||
// If the server responded with "Connection: close", close the connection
|
// If the server responded with "Connection: close", close the connection
|
||||||
// as the server may or may not want to close the socket.
|
// as the server may or may not want to close the socket. Also, if this is
|
||||||
if (auto result = response->headers().get("Connection"sv); result.has_value() && result.value().equals_ignoring_case("close"sv))
|
// a legacy HTTP server (1.0 or older), assume close is the default value.
|
||||||
|
if (auto result = response->headers().get("Connection"sv); result.has_value() ? result->equals_ignoring_case("close"sv) : m_legacy_connection)
|
||||||
shutdown(ShutdownMode::CloseSocket);
|
shutdown(ShutdownMode::CloseSocket);
|
||||||
did_finish(response);
|
did_finish(response);
|
||||||
});
|
});
|
||||||
|
|
|
@ -52,6 +52,7 @@ protected:
|
||||||
HttpRequest m_request;
|
HttpRequest m_request;
|
||||||
State m_state { State::InStatus };
|
State m_state { State::InStatus };
|
||||||
Core::Stream::BufferedSocketBase* m_socket { nullptr };
|
Core::Stream::BufferedSocketBase* m_socket { nullptr };
|
||||||
|
bool m_legacy_connection { false };
|
||||||
int m_code { -1 };
|
int m_code { -1 };
|
||||||
HashMap<String, String, CaseInsensitiveStringTraits> m_headers;
|
HashMap<String, String, CaseInsensitiveStringTraits> m_headers;
|
||||||
Vector<String> m_set_cookie_headers;
|
Vector<String> m_set_cookie_headers;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue