RequestServer: Extract HTTP reason phrase from headers

This commit is contained in:
rmg-x 2024-10-23 16:45:48 -05:00 committed by Ali Mohammad Pur
parent dcf8f2a31d
commit 79046c73da
Notes: github-actions[bot] 2024-11-02 20:06:12 +00:00
3 changed files with 24 additions and 3 deletions
Ladybird/RequestServer
Userland/Services/RequestServer

View file

@ -27,7 +27,7 @@ target_link_libraries(RequestServer PRIVATE requestserverservice)
target_include_directories(requestserverservice PRIVATE ${LADYBIRD_SOURCE_DIR}/Userland/Services/)
target_include_directories(requestserverservice PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
target_link_libraries(requestserverservice PUBLIC LibCore LibMain LibCrypto LibFileSystem LibIPC LibMain LibTLS LibWebView LibWebSocket LibURL LibThreading CURL::libcurl)
target_link_libraries(requestserverservice PUBLIC LibCore LibMain LibCrypto LibFileSystem LibIPC LibMain LibTLS LibWebView LibWebSocket LibURL LibTextCodec LibThreading CURL::libcurl)
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
# Solaris has socket and networking related functions in two extra libraries
target_link_libraries(requestserverservice PUBLIC nsl socket)

View file

@ -13,6 +13,7 @@
#include <LibCore/Proxy.h>
#include <LibCore/Socket.h>
#include <LibRequests/NetworkErrorEnum.h>
#include <LibTextCodec/Decoder.h>
#include <LibWebSocket/ConnectionInfo.h>
#include <LibWebSocket/Message.h>
#include <RequestServer/ConnectionFromClient.h>
@ -37,6 +38,7 @@ struct ConnectionFromClient::ActiveRequest {
bool got_all_headers { false };
size_t downloaded_so_far { 0 };
String url;
Optional<String> reason_phrase;
ByteBuffer body;
ActiveRequest(ConnectionFromClient& client, CURLM* multi, CURL* easy, i32 request_id, int writer_fd)
@ -64,7 +66,7 @@ struct ConnectionFromClient::ActiveRequest {
long http_status_code = 0;
auto result = curl_easy_getinfo(easy, CURLINFO_RESPONSE_CODE, &http_status_code);
VERIFY(result == CURLE_OK);
client->async_headers_became_available(request_id, headers, http_status_code);
client->async_headers_became_available(request_id, headers, http_status_code, reason_phrase);
}
};
@ -73,11 +75,30 @@ size_t ConnectionFromClient::on_header_received(void* buffer, size_t size, size_
auto* request = static_cast<ActiveRequest*>(user_data);
size_t total_size = size * nmemb;
auto header_line = StringView { static_cast<char const*>(buffer), total_size };
// NOTE: We need to extract the HTTP reason phrase since it can be a custom value.
// Fetching infrastructure needs this value for setting the status message.
if (!request->reason_phrase.has_value() && header_line.starts_with("HTTP/"sv)) {
if (auto const space_positions = header_line.find_all(" "sv); space_positions.size() > 1) {
auto const second_space_offset = space_positions.at(1);
auto const reason_phrase_string_view = header_line.substring_view(second_space_offset + 1).trim_whitespace();
if (!reason_phrase_string_view.is_empty()) {
auto decoder = TextCodec::decoder_for_exact_name("ISO-8859-1"sv);
VERIFY(decoder.has_value());
request->reason_phrase = MUST(decoder->to_utf8(reason_phrase_string_view));
return total_size;
}
}
}
if (auto colon_index = header_line.find(':'); colon_index.has_value()) {
auto name = header_line.substring_view(0, colon_index.value()).trim_whitespace();
auto value = header_line.substring_view(colon_index.value() + 1, header_line.length() - colon_index.value() - 1).trim_whitespace();
request->headers.set(name, value);
}
return total_size;
}

View file

@ -6,7 +6,7 @@ endpoint RequestClient
{
request_started(i32 request_id, IPC::File fd) =|
request_finished(i32 request_id, u64 total_size, Optional<Requests::NetworkError> network_error) =|
headers_became_available(i32 request_id, HTTP::HeaderMap response_headers, Optional<u32> status_code) =|
headers_became_available(i32 request_id, HTTP::HeaderMap response_headers, Optional<u32> status_code, Optional<String> reason_phrase) =|
// Websocket API
// FIXME: See if this can be merged with the regular APIs