⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 283427 in webkit


Ignore:
Timestamp:
Oct 1, 2021, 5:22:27 PM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Implement HTTPS proxy in HTTPServer
https://bugs.webkit.org/show_bug.cgi?id=231109

Patch by Alex Christensen <achristensen@webkit.org> on 2021-10-01
Reviewed by Geoff Garen.

Previously we used TCPServer for this, which is picky about the exact number of connections, requests, and replies.
If everything isn't perfect, it hangs in the TCPServer destructor.
It also doesn't run the server logic on the main thread.
This will allow migration to HTTPServer, the replacement for TCPServer.

  • TestWebKitAPI/Tests/WebKitCocoa/Proxy.mm:

(TestWebKitAPI::TEST):

  • TestWebKitAPI/cocoa/HTTPServer.h:
  • TestWebKitAPI/cocoa/HTTPServer.mm:

(TestWebKitAPI::proxyDefinition):
(TestWebKitAPI::HTTPServer::listenerParameters):
(TestWebKitAPI::HTTPServer::respondWithOK):
(TestWebKitAPI::HTTPServer::request const):

Location:
trunk/Tools
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r283391 r283427  
     12021-10-01  Alex Christensen  <achristensen@webkit.org>
     2
     3        Implement HTTPS proxy in HTTPServer
     4        https://bugs.webkit.org/show_bug.cgi?id=231109
     5
     6        Reviewed by Geoff Garen.
     7
     8        Previously we used TCPServer for this, which is picky about the exact number of connections, requests, and replies.
     9        If everything isn't perfect, it hangs in the TCPServer destructor.
     10        It also doesn't run the server logic on the main thread.
     11        This will allow migration to HTTPServer, the replacement for TCPServer.
     12
     13        * TestWebKitAPI/Tests/WebKitCocoa/Proxy.mm:
     14        (TestWebKitAPI::TEST):
     15        * TestWebKitAPI/cocoa/HTTPServer.h:
     16        * TestWebKitAPI/cocoa/HTTPServer.mm:
     17        (TestWebKitAPI::proxyDefinition):
     18        (TestWebKitAPI::HTTPServer::listenerParameters):
     19        (TestWebKitAPI::HTTPServer::respondWithOK):
     20        (TestWebKitAPI::HTTPServer::request const):
     21
    1222021-10-01  Jonathan Bedard  <jbedard@apple.com>
    223
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Proxy.mm

    r275973 r283427  
    7979TEST(WebKit, HTTPSProxy)
    8080{
    81     TCPServer server(TCPServer::Protocol::HTTPSProxy, TCPServer::respondWithOK);
     81    HTTPServer server(HTTPServer::respondWithOK, HTTPServer::Protocol::HttpsProxy);
    8282
    8383    auto storeConfiguration = adoptNS([_WKWebsiteDataStoreConfiguration new]);
  • trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.h

    r283179 r283427  
    4242public:
    4343    struct RequestData;
    44     enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS, Http2 };
     44    enum class Protocol : uint8_t { Http, Https, HttpsWithLegacyTLS, Http2, HttpsProxy };
    4545    using CertificateVerifier = Function<void(sec_protocol_metadata_t, sec_trust_t, sec_protocol_verify_complete_t)>;
    4646
  • trunk/Tools/TestWebKitAPI/cocoa/HTTPServer.mm

    r283272 r283427  
    5353};
    5454
     55static RetainPtr<nw_protocol_definition_t> proxyDefinition()
     56{
     57    return adoptNS(nw_framer_create_definition("HttpsProxy", NW_FRAMER_CREATE_FLAGS_DEFAULT, [] (nw_framer_t framer) -> nw_framer_start_result_t {
     58        nw_framer_set_input_handler(framer, [] (nw_framer_t framer) -> size_t {
     59            nw_framer_parse_input(framer, 1, std::numeric_limits<uint32_t>::max(), nullptr, [retainedFramer = retainPtr(framer)](uint8_t*, size_t bufferLength, bool) mutable -> size_t {
     60                const char* negotiationResponse = ""
     61                    "HTTP/1.1 200 Connection Established\r\n"
     62                    "Connection: close\r\n\r\n";
     63                auto response = adoptNS(dispatch_data_create(negotiationResponse, strlen(negotiationResponse), nullptr, nullptr));
     64                nw_framer_write_output_data(retainedFramer.get(), response.get());
     65                nw_framer_mark_ready(retainedFramer.get());
     66                nw_framer_pass_through_input(retainedFramer.get());
     67                nw_framer_pass_through_output(retainedFramer.get());
     68                retainedFramer = nullptr;
     69                return bufferLength;
     70            });
     71            return 0;
     72        });
     73        return nw_framer_start_result_will_mark_ready;
     74    }));
     75}
     76
    5577RetainPtr<nw_parameters_t> HTTPServer::listenerParameters(Protocol protocol, CertificateVerifier&& verifier, RetainPtr<SecIdentityRef>&& customTestIdentity, std::optional<uint16_t> port)
    5678{
    5779    if (protocol != Protocol::Http && !customTestIdentity)
    5880        customTestIdentity = testIdentity();
    59     auto configureTLS = protocol == Protocol::Http ? makeBlockPtr(NW_PARAMETERS_DISABLE_PROTOCOL) : makeBlockPtr([protocol, verifier = WTFMove(verifier), testIdentity = WTFMove(customTestIdentity)] (nw_protocol_options_t protocolOptions) mutable {
     81
     82    auto configureTLS = [protocol, verifier = WTFMove(verifier), testIdentity = WTFMove(customTestIdentity)] (nw_protocol_options_t protocolOptions) mutable {
    6083#if HAVE(TLS_PROTOCOL_VERSION_T)
    6184        auto options = adoptNS(nw_tls_copy_sec_protocol_options(protocolOptions));
     
    7699        ASSERT_UNUSED(protocol, protocol != Protocol::HttpsWithLegacyTLS);
    77100#endif
    78     });
    79     auto parameters = adoptNS(nw_parameters_create_secure_tcp(configureTLS.get(), NW_PARAMETERS_DEFAULT_CONFIGURATION));
     101    };
     102
     103    auto configureTLSBlock = protocol == Protocol::Http || protocol == Protocol::HttpsProxy ? makeBlockPtr(NW_PARAMETERS_DISABLE_PROTOCOL) : makeBlockPtr(WTFMove(configureTLS));
     104    auto parameters = adoptNS(nw_parameters_create_secure_tcp(configureTLSBlock.get(), NW_PARAMETERS_DEFAULT_CONFIGURATION));
    80105    if (port)
    81106        nw_parameters_set_local_endpoint(parameters.get(), nw_endpoint_create_host("::", makeString(*port).utf8().data()));
     107
     108    if (protocol == Protocol::HttpsProxy) {
     109        auto stack = adoptNS(nw_parameters_copy_default_protocol_stack(parameters.get()));
     110        auto options = adoptNS(nw_framer_create_options(proxyDefinition().get()));
     111        nw_protocol_stack_prepend_application_protocol(stack.get(), options.get());
     112
     113        auto tlsOptions = adoptNS(nw_tls_create_options());
     114        configureTLS(tlsOptions.get());
     115        nw_protocol_stack_prepend_application_protocol(stack.get(), tlsOptions.get());
     116    }
     117
    82118    return parameters;
    83119}
     
    161197        connection.send(
    162198            "HTTP/1.1 200 OK\r\n"
    163             "Content-Length: 13\r\n\r\n"
    164             "Hello, World!"
     199            "Content-Length: 34\r\n\r\n"
     200            "<script>alert('success!')</script>"
    165201        );
    166202    });
     
    269305NSURLRequest *HTTPServer::request(const String& path) const
    270306{
    271     NSString *format;
     307    NSString *format = nil;
    272308    switch (m_protocol) {
    273309    case Protocol::Http:
     
    279315        format = @"https://127.0.0.1:%d%s";
    280316        break;
     317    case Protocol::HttpsProxy:
     318        RELEASE_ASSERT_NOT_REACHED();
    281319    }
    282320    return [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:format, port(), path.utf8().data()]]];
Note: See TracChangeset for help on using the changeset viewer.