1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:47:46 +00:00

RequestServer+LibProtocol: Allow users to specify a per-request proxy

This commit is contained in:
Ali Mohammad Pur 2022-04-07 21:10:33 +04:30 committed by Andreas Kling
parent cd9d740107
commit 45867435c4
16 changed files with 52 additions and 24 deletions

View file

@ -8,7 +8,7 @@
#include "DownloadWidget.h" #include "DownloadWidget.h"
#include <AK/NumberFormat.h> #include <AK/NumberFormat.h>
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <LibConfig/Client.h> #include <LibCore/Proxy.h>
#include <LibCore/StandardPaths.h> #include <LibCore/StandardPaths.h>
#include <LibCore/Stream.h> #include <LibCore/Stream.h>
#include <LibDesktop/Launcher.h> #include <LibDesktop/Launcher.h>
@ -20,9 +20,11 @@
#include <LibGUI/MessageBox.h> #include <LibGUI/MessageBox.h>
#include <LibGUI/Progressbar.h> #include <LibGUI/Progressbar.h>
#include <LibGUI/Window.h> #include <LibGUI/Window.h>
#include <LibProtocol/RequestClient.h>
#include <LibWeb/Loader/ResourceLoader.h> #include <LibWeb/Loader/ResourceLoader.h>
#include <LibConfig/Client.h>
#include <LibProtocol/RequestClient.h>
namespace Browser { namespace Browser {
DownloadWidget::DownloadWidget(const URL& url) DownloadWidget::DownloadWidget(const URL& url)

View file

@ -8,6 +8,7 @@
#include <AK/URL.h> #include <AK/URL.h>
#include <LibCore/AnonymousBuffer.h> #include <LibCore/AnonymousBuffer.h>
#include <LibCore/DateTime.h> #include <LibCore/DateTime.h>
#include <LibCore/Proxy.h>
#include <LibIPC/Decoder.h> #include <LibIPC/Decoder.h>
#include <LibIPC/Dictionary.h> #include <LibIPC/Dictionary.h>
#include <LibIPC/File.h> #include <LibIPC/File.h>
@ -185,4 +186,14 @@ ErrorOr<void> decode(Decoder& decoder, Core::DateTime& datetime)
return {}; return {};
} }
ErrorOr<void> decode(Decoder& decoder, Core::ProxyData& data)
{
UnderlyingType<decltype(data.type)> type;
TRY(decoder.decode(type));
data.type = static_cast<Core::ProxyData::Type>(type);
TRY(decoder.decode(data.host_ipv4));
TRY(decoder.decode(data.port));
return {};
}
} }

View file

@ -11,6 +11,7 @@
#include <AK/URL.h> #include <AK/URL.h>
#include <LibCore/AnonymousBuffer.h> #include <LibCore/AnonymousBuffer.h>
#include <LibCore/DateTime.h> #include <LibCore/DateTime.h>
#include <LibCore/Proxy.h>
#include <LibIPC/Dictionary.h> #include <LibIPC/Dictionary.h>
#include <LibIPC/Encoder.h> #include <LibIPC/Encoder.h>
#include <LibIPC/File.h> #include <LibIPC/File.h>
@ -203,4 +204,12 @@ bool encode(Encoder& encoder, Core::DateTime const& datetime)
return true; return true;
} }
bool encode(Encoder& encoder, Core::ProxyData const& proxy)
{
encoder << to_underlying(proxy.type);
encoder << proxy.host_ipv4;
encoder << proxy.port;
return true;
}
} }

View file

@ -21,7 +21,7 @@ void RequestClient::ensure_connection(URL const& url, ::RequestServer::CacheLeve
} }
template<typename RequestHashMapTraits> template<typename RequestHashMapTraits>
RefPtr<Request> RequestClient::start_request(String const& method, URL const& url, HashMap<String, String, RequestHashMapTraits> const& request_headers, ReadonlyBytes request_body) RefPtr<Request> RequestClient::start_request(String const& method, URL const& url, HashMap<String, String, RequestHashMapTraits> const& request_headers, ReadonlyBytes request_body, Core::ProxyData const& proxy_data)
{ {
IPC::Dictionary header_dictionary; IPC::Dictionary header_dictionary;
for (auto& it : request_headers) for (auto& it : request_headers)
@ -31,7 +31,7 @@ RefPtr<Request> RequestClient::start_request(String const& method, URL const& ur
if (body_result.is_error()) if (body_result.is_error())
return nullptr; return nullptr;
auto response = IPCProxy::start_request(method, url, header_dictionary, body_result.release_value()); auto response = IPCProxy::start_request(method, url, header_dictionary, body_result.release_value(), proxy_data);
auto request_id = response.request_id(); auto request_id = response.request_id();
if (request_id < 0 || !response.response_fd().has_value()) if (request_id < 0 || !response.response_fd().has_value())
return nullptr; return nullptr;
@ -91,5 +91,5 @@ void RequestClient::certificate_requested(i32 request_id)
} }
template RefPtr<Protocol::Request> Protocol::RequestClient::start_request(String const& method, URL const&, HashMap<String, String> const& request_headers, ReadonlyBytes request_body); template RefPtr<Protocol::Request> Protocol::RequestClient::start_request(String const& method, URL const&, HashMap<String, String> const& request_headers, ReadonlyBytes request_body, Core::ProxyData const&);
template RefPtr<Protocol::Request> Protocol::RequestClient::start_request(String const& method, URL const&, HashMap<String, String, CaseInsensitiveStringTraits> const& request_headers, ReadonlyBytes request_body); template RefPtr<Protocol::Request> Protocol::RequestClient::start_request(String const& method, URL const&, HashMap<String, String, CaseInsensitiveStringTraits> const& request_headers, ReadonlyBytes request_body, Core::ProxyData const&);

View file

@ -7,6 +7,8 @@
#pragma once #pragma once
#include <AK/HashMap.h> #include <AK/HashMap.h>
// Need to include this before RequestClientEndpoint.h as that one includes LibIPC/(De En)coder.h, which would bomb if included before this.
#include <LibCore/Proxy.h>
#include <LibIPC/ConnectionToServer.h> #include <LibIPC/ConnectionToServer.h>
#include <RequestServer/RequestClientEndpoint.h> #include <RequestServer/RequestClientEndpoint.h>
#include <RequestServer/RequestServerEndpoint.h> #include <RequestServer/RequestServerEndpoint.h>
@ -22,7 +24,7 @@ class RequestClient final
public: public:
template<typename RequestHashMapTraits = Traits<String>> template<typename RequestHashMapTraits = Traits<String>>
RefPtr<Request> start_request(String const& method, URL const&, HashMap<String, String, RequestHashMapTraits> const& request_headers = {}, ReadonlyBytes request_body = {}); RefPtr<Request> start_request(String const& method, URL const&, HashMap<String, String, RequestHashMapTraits> const& request_headers = {}, ReadonlyBytes request_body = {}, Core::ProxyData const& = {});
void ensure_connection(URL const&, ::RequestServer::CacheLevel); void ensure_connection(URL const&, ::RequestServer::CacheLevel);

View file

@ -6,6 +6,7 @@
#include <AK/Badge.h> #include <AK/Badge.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <LibCore/Proxy.h>
#include <RequestServer/ConnectionFromClient.h> #include <RequestServer/ConnectionFromClient.h>
#include <RequestServer/Protocol.h> #include <RequestServer/Protocol.h>
#include <RequestServer/Request.h> #include <RequestServer/Request.h>
@ -35,7 +36,7 @@ Messages::RequestServer::IsSupportedProtocolResponse ConnectionFromClient::is_su
return supported; return supported;
} }
Messages::RequestServer::StartRequestResponse ConnectionFromClient::start_request(String const& method, URL const& url, IPC::Dictionary const& request_headers, ByteBuffer const& request_body) Messages::RequestServer::StartRequestResponse ConnectionFromClient::start_request(String const& method, URL const& url, IPC::Dictionary const& request_headers, ByteBuffer const& request_body, Core::ProxyData const& proxy_data)
{ {
if (!url.is_valid()) { if (!url.is_valid()) {
dbgln("StartRequest: Invalid URL requested: '{}'", url); dbgln("StartRequest: Invalid URL requested: '{}'", url);
@ -46,7 +47,7 @@ Messages::RequestServer::StartRequestResponse ConnectionFromClient::start_reques
dbgln("StartRequest: No protocol handler for URL: '{}'", url); dbgln("StartRequest: No protocol handler for URL: '{}'", url);
return { -1, Optional<IPC::File> {} }; return { -1, Optional<IPC::File> {} };
} }
auto request = protocol->start_request(*this, method, url, request_headers.entries(), request_body); auto request = protocol->start_request(*this, method, url, request_headers.entries(), request_body, proxy_data);
if (!request) { if (!request) {
dbgln("StartRequest: Protocol handler failed to start request: '{}'", url); dbgln("StartRequest: Protocol handler failed to start request: '{}'", url);
return { -1, Optional<IPC::File> {} }; return { -1, Optional<IPC::File> {} };

View file

@ -7,6 +7,8 @@
#pragma once #pragma once
#include <AK/HashMap.h> #include <AK/HashMap.h>
// Need to include this before RequestClientEndpoint.h as that one includes LibIPC/(De En)coder.h, which would bomb if included before this.
#include <LibCore/Proxy.h>
#include <LibIPC/ConnectionFromClient.h> #include <LibIPC/ConnectionFromClient.h>
#include <RequestServer/Forward.h> #include <RequestServer/Forward.h>
#include <RequestServer/RequestClientEndpoint.h> #include <RequestServer/RequestClientEndpoint.h>
@ -32,7 +34,7 @@ private:
explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>); explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>);
virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(String const&) override; virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(String const&) override;
virtual Messages::RequestServer::StartRequestResponse start_request(String const&, URL const&, IPC::Dictionary const&, ByteBuffer const&) override; virtual Messages::RequestServer::StartRequestResponse start_request(String const&, URL const&, IPC::Dictionary const&, ByteBuffer const&, Core::ProxyData const&) override;
virtual Messages::RequestServer::StopRequestResponse stop_request(i32) override; virtual Messages::RequestServer::StopRequestResponse stop_request(i32) override;
virtual Messages::RequestServer::SetCertificateResponse set_certificate(i32, String const&, String const&) override; virtual Messages::RequestServer::SetCertificateResponse set_certificate(i32, String const&, String const&) override;
virtual void ensure_connection(URL const& url, ::RequestServer::CacheLevel const& cache_level) override; virtual void ensure_connection(URL const& url, ::RequestServer::CacheLevel const& cache_level) override;

View file

@ -17,7 +17,7 @@ GeminiProtocol::GeminiProtocol()
{ {
} }
OwnPtr<Request> GeminiProtocol::start_request(ConnectionFromClient& client, String const&, const URL& url, HashMap<String, String> const&, ReadonlyBytes) OwnPtr<Request> GeminiProtocol::start_request(ConnectionFromClient& client, String const&, const URL& url, HashMap<String, String> const&, ReadonlyBytes, Core::ProxyData proxy_data)
{ {
Gemini::GeminiRequest request; Gemini::GeminiRequest request;
request.set_url(url); request.set_url(url);
@ -31,7 +31,7 @@ OwnPtr<Request> GeminiProtocol::start_request(ConnectionFromClient& client, Stri
auto protocol_request = GeminiRequest::create_with_job({}, client, *job, move(output_stream)); auto protocol_request = GeminiRequest::create_with_job({}, client, *job, move(output_stream));
protocol_request->set_request_fd(pipe_result.value().read_fd); protocol_request->set_request_fd(pipe_result.value().read_fd);
ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, *job); ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, *job, proxy_data);
return protocol_request; return protocol_request;
} }

View file

@ -15,7 +15,7 @@ public:
GeminiProtocol(); GeminiProtocol();
virtual ~GeminiProtocol() override = default; virtual ~GeminiProtocol() override = default;
virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const&, ReadonlyBytes body) override; virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const&, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
}; };
} }

View file

@ -61,7 +61,7 @@ void init(TSelf* self, TJob job)
} }
template<typename TBadgedProtocol, typename TPipeResult> template<typename TBadgedProtocol, typename TPipeResult>
OwnPtr<Request> start_request(TBadgedProtocol&& protocol, ConnectionFromClient& client, String const& method, const URL& url, HashMap<String, String> const& headers, ReadonlyBytes body, TPipeResult&& pipe_result) OwnPtr<Request> start_request(TBadgedProtocol&& protocol, ConnectionFromClient& client, String const& method, const URL& url, HashMap<String, String> const& headers, ReadonlyBytes body, TPipeResult&& pipe_result, Core::ProxyData proxy_data = {})
{ {
using TJob = typename TBadgedProtocol::Type::JobType; using TJob = typename TBadgedProtocol::Type::JobType;
using TRequest = typename TBadgedProtocol::Type::RequestType; using TRequest = typename TBadgedProtocol::Type::RequestType;
@ -89,9 +89,9 @@ OwnPtr<Request> start_request(TBadgedProtocol&& protocol, ConnectionFromClient&
protocol_request->set_request_fd(pipe_result.value().read_fd); protocol_request->set_request_fd(pipe_result.value().read_fd);
if constexpr (IsSame<typename TBadgedProtocol::Type, HttpsProtocol>) if constexpr (IsSame<typename TBadgedProtocol::Type, HttpsProtocol>)
ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, *job); ConnectionCache::get_or_create_connection(ConnectionCache::g_tls_connection_cache, url, *job, proxy_data);
else else
ConnectionCache::get_or_create_connection(ConnectionCache::g_tcp_connection_cache, url, *job); ConnectionCache::get_or_create_connection(ConnectionCache::g_tcp_connection_cache, url, *job, proxy_data);
return protocol_request; return protocol_request;
} }

View file

@ -22,9 +22,9 @@ HttpProtocol::HttpProtocol()
{ {
} }
OwnPtr<Request> HttpProtocol::start_request(ConnectionFromClient& client, String const& method, const URL& url, HashMap<String, String> const& headers, ReadonlyBytes body) OwnPtr<Request> HttpProtocol::start_request(ConnectionFromClient& client, String const& method, const URL& url, HashMap<String, String> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data)
{ {
return Detail::start_request(Badge<HttpProtocol> {}, client, method, url, headers, body, get_pipe_for_request()); return Detail::start_request(Badge<HttpProtocol> {}, client, method, url, headers, body, get_pipe_for_request(), proxy_data);
} }
} }

View file

@ -27,7 +27,7 @@ public:
HttpProtocol(); HttpProtocol();
~HttpProtocol() override = default; ~HttpProtocol() override = default;
virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const& headers, ReadonlyBytes body) override; virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
}; };
} }

View file

@ -22,9 +22,9 @@ HttpsProtocol::HttpsProtocol()
{ {
} }
OwnPtr<Request> HttpsProtocol::start_request(ConnectionFromClient& client, String const& method, const URL& url, HashMap<String, String> const& headers, ReadonlyBytes body) OwnPtr<Request> HttpsProtocol::start_request(ConnectionFromClient& client, String const& method, const URL& url, HashMap<String, String> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data)
{ {
return Detail::start_request(Badge<HttpsProtocol> {}, client, method, url, headers, body, get_pipe_for_request()); return Detail::start_request(Badge<HttpsProtocol> {}, client, method, url, headers, body, get_pipe_for_request(), proxy_data);
} }
} }

View file

@ -27,7 +27,7 @@ public:
HttpsProtocol(); HttpsProtocol();
~HttpsProtocol() override = default; ~HttpsProtocol() override = default;
virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const& headers, ReadonlyBytes body) override; virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) override;
}; };
} }

View file

@ -8,6 +8,7 @@
#include <AK/RefPtr.h> #include <AK/RefPtr.h>
#include <AK/URL.h> #include <AK/URL.h>
#include <LibCore/Proxy.h>
#include <RequestServer/Forward.h> #include <RequestServer/Forward.h>
namespace RequestServer { namespace RequestServer {
@ -17,7 +18,7 @@ public:
virtual ~Protocol(); virtual ~Protocol();
String const& name() const { return m_name; } String const& name() const { return m_name; }
virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const& headers, ReadonlyBytes body) = 0; virtual OwnPtr<Request> start_request(ConnectionFromClient&, String const& method, const URL&, HashMap<String, String> const& headers, ReadonlyBytes body, Core::ProxyData proxy_data = {}) = 0;
static Protocol* find_by_name(String const&); static Protocol* find_by_name(String const&);

View file

@ -6,7 +6,7 @@ endpoint RequestServer
// Test if a specific protocol is supported, e.g "http" // Test if a specific protocol is supported, e.g "http"
is_supported_protocol(String protocol) => (bool supported) is_supported_protocol(String protocol) => (bool supported)
start_request(String method, URL url, IPC::Dictionary request_headers, ByteBuffer request_body) => (i32 request_id, Optional<IPC::File> response_fd) start_request(String method, URL url, IPC::Dictionary request_headers, ByteBuffer request_body, Core::ProxyData proxy_data) => (i32 request_id, Optional<IPC::File> response_fd)
stop_request(i32 request_id) => (bool success) stop_request(i32 request_id) => (bool success)
set_certificate(i32 request_id, String certificate, String key) => (bool success) set_certificate(i32 request_id, String certificate, String key) => (bool success)