diff options
author | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:17:30 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-12 12:17:46 +0100 |
commit | 13d7c09125f8eec703d0a43a9a87fc8aa08f7319 (patch) | |
tree | 70fd643c429cea5c1f9362c2674511d17a53f3b5 /Libraries/LibHTTP | |
parent | dc28c07fa526841e05e16161c74a6c23984f1dd5 (diff) | |
download | serenity-13d7c09125f8eec703d0a43a9a87fc8aa08f7319.zip |
Libraries: Move to Userland/Libraries/
Diffstat (limited to 'Libraries/LibHTTP')
-rw-r--r-- | Libraries/LibHTTP/CMakeLists.txt | 10 | ||||
-rw-r--r-- | Libraries/LibHTTP/Forward.h | 37 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpJob.cpp | 106 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpJob.h | 69 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpRequest.cpp | 195 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpRequest.h | 83 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpResponse.cpp | 41 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpResponse.h | 53 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpsJob.cpp | 151 | ||||
-rw-r--r-- | Libraries/LibHTTP/HttpsJob.h | 75 | ||||
-rw-r--r-- | Libraries/LibHTTP/Job.cpp | 405 | ||||
-rw-r--r-- | Libraries/LibHTTP/Job.h | 87 |
12 files changed, 0 insertions, 1312 deletions
diff --git a/Libraries/LibHTTP/CMakeLists.txt b/Libraries/LibHTTP/CMakeLists.txt deleted file mode 100644 index 57c79b55e2..0000000000 --- a/Libraries/LibHTTP/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -set(SOURCES - HttpJob.cpp - HttpRequest.cpp - HttpResponse.cpp - HttpsJob.cpp - Job.cpp -) - -serenity_lib(LibHTTP http) -target_link_libraries(LibHTTP LibCore LibTLS) diff --git a/Libraries/LibHTTP/Forward.h b/Libraries/LibHTTP/Forward.h deleted file mode 100644 index bb64e1d25b..0000000000 --- a/Libraries/LibHTTP/Forward.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2020, The SerenityOS developers. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -namespace HTTP { - -class HttpRequest; -class HttpResponse; -class HttpJob; -class HttpsJob; -class Job; - -} diff --git a/Libraries/LibHTTP/HttpJob.cpp b/Libraries/LibHTTP/HttpJob.cpp deleted file mode 100644 index 87db14756d..0000000000 --- a/Libraries/LibHTTP/HttpJob.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <LibCore/Gzip.h> -#include <LibCore/TCPSocket.h> -#include <LibHTTP/HttpJob.h> -#include <LibHTTP/HttpResponse.h> -#include <stdio.h> -#include <unistd.h> - -//#define HTTPJOB_DEBUG - -namespace HTTP { -void HttpJob::start() -{ - ASSERT(!m_socket); - m_socket = Core::TCPSocket::construct(this); - m_socket->on_connected = [this] { -#ifdef CHTTPJOB_DEBUG - dbgln("HttpJob: on_connected callback"); -#endif - on_socket_connected(); - }; - bool success = m_socket->connect(m_request.url().host(), m_request.url().port()); - if (!success) { - deferred_invoke([this](auto&) { - return did_fail(Core::NetworkJob::Error::ConnectionFailed); - }); - } -} - -void HttpJob::shutdown() -{ - if (!m_socket) - return; - m_socket->on_ready_to_read = nullptr; - m_socket->on_connected = nullptr; - remove_child(*m_socket); - m_socket = nullptr; -} - -void HttpJob::register_on_ready_to_read(Function<void()> callback) -{ - m_socket->on_ready_to_read = move(callback); -} - -void HttpJob::register_on_ready_to_write(Function<void()> callback) -{ - // There is no need to wait, the connection is already established - callback(); -} - -bool HttpJob::can_read_line() const -{ - return m_socket->can_read_line(); -} - -String HttpJob::read_line(size_t size) -{ - return m_socket->read_line(size); -} - -ByteBuffer HttpJob::receive(size_t size) -{ - return m_socket->receive(size); -} - -bool HttpJob::can_read() const -{ - return m_socket->can_read(); -} - -bool HttpJob::eof() const -{ - return m_socket->eof(); -} - -bool HttpJob::write(ReadonlyBytes bytes) -{ - return m_socket->write(bytes); -} - -} diff --git a/Libraries/LibHTTP/HttpJob.h b/Libraries/LibHTTP/HttpJob.h deleted file mode 100644 index 924ff6bf5f..0000000000 --- a/Libraries/LibHTTP/HttpJob.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include <AK/HashMap.h> -#include <LibCore/NetworkJob.h> -#include <LibCore/TCPSocket.h> -#include <LibHTTP/HttpRequest.h> -#include <LibHTTP/HttpResponse.h> -#include <LibHTTP/Job.h> - -namespace HTTP { - -class HttpJob final : public Job { - C_OBJECT(HttpJob) -public: - explicit HttpJob(const HttpRequest& request, OutputStream& output_stream) - : Job(request, output_stream) - { - } - - virtual ~HttpJob() override - { - } - - virtual void start() override; - virtual void shutdown() override; - -protected: - virtual bool should_fail_on_empty_payload() const override { return false; } - virtual void register_on_ready_to_read(Function<void()>) override; - virtual void register_on_ready_to_write(Function<void()>) override; - virtual bool can_read_line() const override; - virtual String read_line(size_t) override; - virtual bool can_read() const override; - virtual ByteBuffer receive(size_t) override; - virtual bool eof() const override; - virtual bool write(ReadonlyBytes) override; - virtual bool is_established() const override { return true; } - -private: - RefPtr<Core::Socket> m_socket; -}; - -} diff --git a/Libraries/LibHTTP/HttpRequest.cpp b/Libraries/LibHTTP/HttpRequest.cpp deleted file mode 100644 index 8ea42a4e84..0000000000 --- a/Libraries/LibHTTP/HttpRequest.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <AK/StringBuilder.h> -#include <LibHTTP/HttpJob.h> -#include <LibHTTP/HttpRequest.h> - -namespace HTTP { - -HttpRequest::HttpRequest() -{ -} - -HttpRequest::~HttpRequest() -{ -} - -String HttpRequest::method_name() const -{ - switch (m_method) { - case Method::GET: - return "GET"; - case Method::HEAD: - return "HEAD"; - case Method::POST: - return "POST"; - default: - ASSERT_NOT_REACHED(); - } -} - -ByteBuffer HttpRequest::to_raw_request() const -{ - StringBuilder builder; - builder.append(method_name()); - builder.append(' '); - builder.append(m_url.path()); - if (!m_url.query().is_empty()) { - builder.append('?'); - builder.append(m_url.query()); - } - builder.append(" HTTP/1.1\r\nHost: "); - builder.append(m_url.host()); - builder.append("\r\n"); - for (auto& header : m_headers) { - builder.append(header.name); - builder.append(": "); - builder.append(header.value); - builder.append("\r\n"); - } - builder.append("Connection: close\r\n"); - if (!m_body.is_empty()) { - builder.appendff("Content-Length: {}\r\n\r\n", m_body.size()); - builder.append((const char*)m_body.data(), m_body.size()); - } - builder.append("\r\n"); - return builder.to_byte_buffer(); -} - -Optional<HttpRequest> HttpRequest::from_raw_request(ReadonlyBytes raw_request) -{ - enum class State { - InMethod, - InResource, - InProtocol, - InHeaderName, - InHeaderValue, - }; - - State state { State::InMethod }; - size_t index = 0; - - auto peek = [&](int offset = 0) -> u8 { - if (index + offset >= raw_request.size()) - return 0; - return raw_request[index + offset]; - }; - - auto consume = [&]() -> u8 { - ASSERT(index < raw_request.size()); - return raw_request[index++]; - }; - - Vector<u8, 256> buffer; - - String method; - String resource; - String protocol; - Vector<Header> headers; - Header current_header; - - auto commit_and_advance_to = [&](auto& output, State new_state) { - output = String::copy(buffer); - buffer.clear(); - state = new_state; - }; - - while (index < raw_request.size()) { - // FIXME: Figure out what the appropriate limitations should be. - if (buffer.size() > 65536) - return {}; - switch (state) { - case State::InMethod: - if (peek() == ' ') { - consume(); - commit_and_advance_to(method, State::InResource); - break; - } - buffer.append(consume()); - break; - case State::InResource: - if (peek() == ' ') { - consume(); - commit_and_advance_to(resource, State::InProtocol); - break; - } - buffer.append(consume()); - break; - case State::InProtocol: - if (peek(0) == '\r' && peek(1) == '\n') { - consume(); - consume(); - commit_and_advance_to(protocol, State::InHeaderName); - break; - } - buffer.append(consume()); - break; - case State::InHeaderName: - if (peek(0) == ':' && peek(1) == ' ') { - consume(); - consume(); - commit_and_advance_to(current_header.name, State::InHeaderValue); - break; - } - buffer.append(consume()); - break; - case State::InHeaderValue: - if (peek(0) == '\r' && peek(1) == '\n') { - consume(); - consume(); - commit_and_advance_to(current_header.value, State::InHeaderName); - headers.append(move(current_header)); - break; - } - buffer.append(consume()); - break; - } - } - - HttpRequest request; - if (method == "GET") - request.m_method = Method::GET; - else if (method == "HEAD") - request.m_method = Method::HEAD; - else if (method == "POST") - request.m_method = Method::POST; - else - return {}; - - request.m_resource = resource; - request.m_headers = move(headers); - - return request; -} - -void HttpRequest::set_headers(const HashMap<String, String>& headers) -{ - for (auto& it : headers) - m_headers.append({ it.key, it.value }); -} - -} diff --git a/Libraries/LibHTTP/HttpRequest.h b/Libraries/LibHTTP/HttpRequest.h deleted file mode 100644 index c1a92d33eb..0000000000 --- a/Libraries/LibHTTP/HttpRequest.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include <AK/ByteBuffer.h> -#include <AK/Optional.h> -#include <AK/String.h> -#include <AK/URL.h> -#include <AK/Vector.h> -#include <LibCore/Forward.h> - -namespace HTTP { - -class HttpRequest { -public: - enum Method { - Invalid, - HEAD, - GET, - POST - }; - - struct Header { - String name; - String value; - }; - - HttpRequest(); - ~HttpRequest(); - - const String& resource() const { return m_resource; } - const Vector<Header>& headers() const { return m_headers; } - - const URL& url() const { return m_url; } - void set_url(const URL& url) { m_url = url; } - - Method method() const { return m_method; } - void set_method(Method method) { m_method = method; } - - const ByteBuffer& body() const { return m_body; } - void set_body(ReadonlyBytes body) { m_body = ByteBuffer::copy(body); } - void set_body(ByteBuffer&& body) { m_body = move(body); } - - String method_name() const; - ByteBuffer to_raw_request() const; - - void set_headers(const HashMap<String, String>&); - - static Optional<HttpRequest> from_raw_request(ReadonlyBytes); - -private: - URL m_url; - String m_resource; - Method m_method { GET }; - Vector<Header> m_headers; - ByteBuffer m_body; -}; - -} diff --git a/Libraries/LibHTTP/HttpResponse.cpp b/Libraries/LibHTTP/HttpResponse.cpp deleted file mode 100644 index 61571577ca..0000000000 --- a/Libraries/LibHTTP/HttpResponse.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <LibHTTP/HttpResponse.h> - -namespace HTTP { - -HttpResponse::HttpResponse(int code, HashMap<String, String, CaseInsensitiveStringTraits>&& headers) - : m_code(code) - , m_headers(move(headers)) -{ -} - -HttpResponse::~HttpResponse() -{ -} - -} diff --git a/Libraries/LibHTTP/HttpResponse.h b/Libraries/LibHTTP/HttpResponse.h deleted file mode 100644 index a5e9fa74dc..0000000000 --- a/Libraries/LibHTTP/HttpResponse.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include <AK/HashMap.h> -#include <AK/String.h> -#include <LibCore/NetworkResponse.h> - -namespace HTTP { - -class HttpResponse : public Core::NetworkResponse { -public: - virtual ~HttpResponse() override; - static NonnullRefPtr<HttpResponse> create(int code, HashMap<String, String, CaseInsensitiveStringTraits>&& headers) - { - return adopt(*new HttpResponse(code, move(headers))); - } - - int code() const { return m_code; } - const HashMap<String, String, CaseInsensitiveStringTraits>& headers() const { return m_headers; } - -private: - HttpResponse(int code, HashMap<String, String, CaseInsensitiveStringTraits>&&); - - int m_code { 0 }; - HashMap<String, String, CaseInsensitiveStringTraits> m_headers; -}; - -} diff --git a/Libraries/LibHTTP/HttpsJob.cpp b/Libraries/LibHTTP/HttpsJob.cpp deleted file mode 100644 index ab12ee971a..0000000000 --- a/Libraries/LibHTTP/HttpsJob.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2020, The SerenityOS developers. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <LibCore/EventLoop.h> -#include <LibCore/Gzip.h> -#include <LibHTTP/HttpResponse.h> -#include <LibHTTP/HttpsJob.h> -#include <LibTLS/TLSv12.h> -#include <stdio.h> -#include <unistd.h> - -//#define HTTPSJOB_DEBUG - -namespace HTTP { - -void HttpsJob::start() -{ - ASSERT(!m_socket); - m_socket = TLS::TLSv12::construct(this); - m_socket->set_root_certificates(m_override_ca_certificates ? *m_override_ca_certificates : DefaultRootCACertificates::the().certificates()); - m_socket->on_tls_connected = [this] { -#ifdef HTTPSJOB_DEBUG - dbgln("HttpsJob: on_connected callback"); -#endif - on_socket_connected(); - }; - m_socket->on_tls_error = [&](TLS::AlertDescription error) { - if (error == TLS::AlertDescription::HandshakeFailure) { - deferred_invoke([this](auto&) { - return did_fail(Core::NetworkJob::Error::ProtocolFailed); - }); - } else if (error == TLS::AlertDescription::DecryptError) { - deferred_invoke([this](auto&) { - return did_fail(Core::NetworkJob::Error::ConnectionFailed); - }); - } else { - deferred_invoke([this](auto&) { - return did_fail(Core::NetworkJob::Error::TransmissionFailed); - }); - } - }; - m_socket->on_tls_finished = [&] { - finish_up(); - }; - m_socket->on_tls_certificate_request = [this](auto&) { - if (on_certificate_requested) - on_certificate_requested(*this); - }; - bool success = ((TLS::TLSv12&)*m_socket).connect(m_request.url().host(), m_request.url().port()); - if (!success) { - deferred_invoke([this](auto&) { - return did_fail(Core::NetworkJob::Error::ConnectionFailed); - }); - } -} - -void HttpsJob::shutdown() -{ - if (!m_socket) - return; - m_socket->on_tls_ready_to_read = nullptr; - m_socket->on_tls_connected = nullptr; - remove_child(*m_socket); - m_socket = nullptr; -} - -void HttpsJob::set_certificate(String certificate, String private_key) -{ - if (!m_socket->add_client_key(certificate.bytes(), private_key.bytes())) { - dbgln("LibHTTP: Failed to set a client certificate"); - // FIXME: Do something about this failure - ASSERT_NOT_REACHED(); - } -} - -void HttpsJob::read_while_data_available(Function<IterationDecision()> read) -{ - while (m_socket->can_read()) { - if (read() == IterationDecision::Break) - break; - } -} - -void HttpsJob::register_on_ready_to_read(Function<void()> callback) -{ - m_socket->on_tls_ready_to_read = [callback = move(callback)](auto&) { - callback(); - }; -} - -void HttpsJob::register_on_ready_to_write(Function<void()> callback) -{ - m_socket->on_tls_ready_to_write = [callback = move(callback)](auto&) { - callback(); - }; -} - -bool HttpsJob::can_read_line() const -{ - return m_socket->can_read_line(); -} - -String HttpsJob::read_line(size_t size) -{ - return m_socket->read_line(size); -} - -ByteBuffer HttpsJob::receive(size_t size) -{ - return m_socket->read(size); -} - -bool HttpsJob::can_read() const -{ - return m_socket->can_read(); -} - -bool HttpsJob::eof() const -{ - return m_socket->eof(); -} - -bool HttpsJob::write(ReadonlyBytes data) -{ - return m_socket->write(data); -} - -} diff --git a/Libraries/LibHTTP/HttpsJob.h b/Libraries/LibHTTP/HttpsJob.h deleted file mode 100644 index 7ead5fbf48..0000000000 --- a/Libraries/LibHTTP/HttpsJob.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2020, The SerenityOS developers. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include <AK/HashMap.h> -#include <LibCore/NetworkJob.h> -#include <LibHTTP/HttpRequest.h> -#include <LibHTTP/HttpResponse.h> -#include <LibHTTP/Job.h> -#include <LibTLS/TLSv12.h> - -namespace HTTP { - -class HttpsJob final : public Job { - C_OBJECT(HttpsJob) -public: - explicit HttpsJob(const HttpRequest& request, OutputStream& output_stream, const Vector<Certificate>* override_certs = nullptr) - : Job(request, output_stream) - , m_override_ca_certificates(override_certs) - { - } - - virtual ~HttpsJob() override - { - } - - virtual void start() override; - virtual void shutdown() override; - void set_certificate(String certificate, String key); - - Function<void(HttpsJob&)> on_certificate_requested; - -protected: - virtual void register_on_ready_to_read(Function<void()>) override; - virtual void register_on_ready_to_write(Function<void()>) override; - virtual bool can_read_line() const override; - virtual String read_line(size_t) override; - virtual bool can_read() const override; - virtual ByteBuffer receive(size_t) override; - virtual bool eof() const override; - virtual bool write(ReadonlyBytes) override; - virtual bool is_established() const override { return m_socket->is_established(); } - virtual bool should_fail_on_empty_payload() const override { return false; } - virtual void read_while_data_available(Function<IterationDecision()>) override; - -private: - RefPtr<TLS::TLSv12> m_socket; - const Vector<Certificate>* m_override_ca_certificates { nullptr }; -}; - -} diff --git a/Libraries/LibHTTP/Job.cpp b/Libraries/LibHTTP/Job.cpp deleted file mode 100644 index af3f53c19b..0000000000 --- a/Libraries/LibHTTP/Job.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <LibCore/Gzip.h> -#include <LibCore/TCPSocket.h> -#include <LibHTTP/HttpResponse.h> -#include <LibHTTP/Job.h> -#include <stdio.h> -#include <unistd.h> - -//#define JOB_DEBUG - -namespace HTTP { - -static ByteBuffer handle_content_encoding(const ByteBuffer& buf, const String& content_encoding) -{ -#ifdef JOB_DEBUG - dbg() << "Job::handle_content_encoding: buf has content_encoding = " << content_encoding; -#endif - - if (content_encoding == "gzip") { - if (!Core::Gzip::is_compressed(buf)) { - dbgln("Job::handle_content_encoding: buf is not gzip compressed!"); - } - -#ifdef JOB_DEBUG - dbgln("Job::handle_content_encoding: buf is gzip compressed!"); -#endif - - auto uncompressed = Core::Gzip::decompress(buf); - if (!uncompressed.has_value()) { - dbgln("Job::handle_content_encoding: Gzip::decompress() failed. Returning original buffer."); - return buf; - } - -#ifdef JOB_DEBUG - dbg() << "Job::handle_content_encoding: Gzip::decompress() successful.\n" - << " Input size = " << buf.size() << "\n" - << " Output size = " << uncompressed.value().size(); -#endif - - return uncompressed.value(); - } - - return buf; -} - -Job::Job(const HttpRequest& request, OutputStream& output_stream) - : Core::NetworkJob(output_stream) - , m_request(request) -{ -} - -Job::~Job() -{ -} - -void Job::flush_received_buffers() -{ - if (!m_can_stream_response || m_buffered_size == 0) - return; -#ifdef JOB_DEBUG - dbg() << "Job: Flushing received buffers: have " << m_buffered_size << " bytes in " << m_received_buffers.size() << " buffers"; -#endif - for (size_t i = 0; i < m_received_buffers.size(); ++i) { - auto& payload = m_received_buffers[i]; - auto written = do_write(payload); - m_buffered_size -= written; - if (written == payload.size()) { - // FIXME: Make this a take-first-friendly object? - m_received_buffers.take_first(); - --i; - continue; - } - ASSERT(written < payload.size()); - payload = payload.slice(written, payload.size() - written); -#ifdef JOB_DEBUG - dbg() << "Job: Flushing received buffers done: have " << m_buffered_size << " bytes in " << m_received_buffers.size() << " buffers"; -#endif - return; - } -#ifdef JOB_DEBUG - dbg() << "Job: Flushing received buffers done: have " << m_buffered_size << " bytes in " << m_received_buffers.size() << " buffers"; -#endif -} - -void Job::on_socket_connected() -{ - register_on_ready_to_write([&] { - if (m_sent_data) - return; - m_sent_data = true; - auto raw_request = m_request.to_raw_request(); -#ifdef JOB_DEBUG - dbgln("Job: raw_request:"); - dbg() << String::copy(raw_request).characters(); -#endif - bool success = write(raw_request); - if (!success) - deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::TransmissionFailed); }); - }); - register_on_ready_to_read([&] { - if (is_cancelled()) - return; - - if (m_state == State::Finished) { - // This is probably just a EOF notification, which means we should receive nothing - // and then get eof() == true. - [[maybe_unused]] auto payload = receive(64); - // These assertions are only correct if "Connection: close". - ASSERT(payload.is_empty()); - ASSERT(eof()); - return; - } - - if (m_state == State::InStatus) { - if (!can_read_line()) - return; - auto line = read_line(PAGE_SIZE); - if (line.is_null()) { - fprintf(stderr, "Job: Expected HTTP status\n"); - return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::TransmissionFailed); }); - } - auto parts = line.split_view(' '); - if (parts.size() < 3) { - warnln("Job: Expected 3-part HTTP status, got '{}'", line); - return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); - } - auto code = parts[1].to_uint(); - if (!code.has_value()) { - fprintf(stderr, "Job: Expected numeric HTTP status\n"); - return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); - } - m_code = code.value(); - m_state = State::InHeaders; - return; - } - if (m_state == State::InHeaders || m_state == State::Trailers) { - if (!can_read_line()) - return; - auto line = read_line(PAGE_SIZE); - if (line.is_null()) { - if (m_state == State::Trailers) { - // Some servers like to send two ending chunks - // use this fact as an excuse to ignore anything after the last chunk - // that is not a valid trailing header. - return finish_up(); - } - fprintf(stderr, "Job: Expected HTTP header\n"); - return did_fail(Core::NetworkJob::Error::ProtocolFailed); - } - if (line.is_empty()) { - if (m_state == State::Trailers) { - return finish_up(); - } else { - if (on_headers_received) - on_headers_received(m_headers, m_code > 0 ? m_code : Optional<u32> {}); - m_state = State::InBody; - } - return; - } - auto parts = line.split_view(':'); - if (parts.is_empty()) { - if (m_state == State::Trailers) { - // Some servers like to send two ending chunks - // use this fact as an excuse to ignore anything after the last chunk - // that is not a valid trailing header. - return finish_up(); - } - fprintf(stderr, "Job: Expected HTTP header with key/value\n"); - return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); - } - auto name = parts[0]; - if (line.length() < name.length() + 2) { - if (m_state == State::Trailers) { - // Some servers like to send two ending chunks - // use this fact as an excuse to ignore anything after the last chunk - // that is not a valid trailing header. - return finish_up(); - } - warnln("Job: Malformed HTTP header: '{}' ({})", line, line.length()); - return deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); - } - auto value = line.substring(name.length() + 2, line.length() - name.length() - 2); - m_headers.set(name, value); - if (name.equals_ignoring_case("Content-Encoding")) { - // Assume that any content-encoding means that we can't decode it as a stream :( -#ifdef JOB_DEBUG - dbg() << "Content-Encoding " << value << " detected, cannot stream output :("; -#endif - m_can_stream_response = false; - } -#ifdef JOB_DEBUG - dbg() << "Job: [" << name << "] = '" << value << "'"; -#endif - return; - } - ASSERT(m_state == State::InBody); - ASSERT(can_read()); - - read_while_data_available([&] { - auto read_size = 64 * KiB; - if (m_current_chunk_remaining_size.has_value()) { - read_chunk_size:; - auto remaining = m_current_chunk_remaining_size.value(); - if (remaining == -1) { - // read size - auto size_data = read_line(PAGE_SIZE); - auto size_lines = size_data.view().lines(); -#ifdef JOB_DEBUG - dbg() << "Job: Received a chunk with size _" << size_data << "_"; -#endif - if (size_lines.size() == 0) { - dbgln("Job: Reached end of stream"); - finish_up(); - return IterationDecision::Break; - } else { - auto chunk = size_lines[0].split_view(';', true); - String size_string = chunk[0]; - char* endptr; - auto size = strtoul(size_string.characters(), &endptr, 16); - if (*endptr) { - // invalid number - deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::TransmissionFailed); }); - return IterationDecision::Break; - } - if (size == 0) { - // This is the last chunk - // '0' *[; chunk-ext-name = chunk-ext-value] - // We're going to ignore _all_ chunk extensions - read_size = 0; - m_current_chunk_total_size = 0; - m_current_chunk_remaining_size = 0; -#ifdef JOB_DEBUG - dbg() << "Job: Received the last chunk with extensions _" << size_string.substring_view(1, size_string.length() - 1) << "_"; -#endif - } else { - m_current_chunk_total_size = size; - m_current_chunk_remaining_size = size; - read_size = size; -#ifdef JOB_DEBUG - dbg() << "Job: Chunk of size _" << size << "_ started"; -#endif - } - } - } else { - read_size = remaining; -#ifdef JOB_DEBUG - dbg() << "Job: Resuming chunk with _" << remaining << "_ bytes left over"; -#endif - } - } else { - auto transfer_encoding = m_headers.get("Transfer-Encoding"); - if (transfer_encoding.has_value()) { - auto encoding = transfer_encoding.value(); -#ifdef JOB_DEBUG - dbg() << "Job: This content has transfer encoding '" << encoding << "'"; -#endif - if (encoding.equals_ignoring_case("chunked")) { - m_current_chunk_remaining_size = -1; - goto read_chunk_size; - } else { - dbg() << "Job: Unknown transfer encoding _" << encoding << "_, the result will likely be wrong!"; - } - } - } - - auto payload = receive(read_size); - if (!payload) { - if (eof()) { - finish_up(); - return IterationDecision::Break; - } - - if (should_fail_on_empty_payload()) { - deferred_invoke([this](auto&) { did_fail(Core::NetworkJob::Error::ProtocolFailed); }); - return IterationDecision::Break; - } - } - - m_received_buffers.append(payload); - m_buffered_size += payload.size(); - m_received_size += payload.size(); - flush_received_buffers(); - - if (m_current_chunk_remaining_size.has_value()) { - auto size = m_current_chunk_remaining_size.value() - payload.size(); -#ifdef JOB_DEBUG - dbg() << "Job: We have " << size << " bytes left over in this chunk"; -#endif - if (size == 0) { -#ifdef JOB_DEBUG - dbg() << "Job: Finished a chunk of " << m_current_chunk_total_size.value() << " bytes"; -#endif - - if (m_current_chunk_total_size.value() == 0) { - m_state = State::Trailers; - return IterationDecision::Break; - } - - // we've read everything, now let's get the next chunk - size = -1; - [[maybe_unused]] auto line = read_line(PAGE_SIZE); -#ifdef JOB_DEBUG - dbg() << "Line following (should be empty): _" << line << "_"; -#endif - } - m_current_chunk_remaining_size = size; - } - - auto content_length_header = m_headers.get("Content-Length"); - Optional<u32> content_length {}; - - if (content_length_header.has_value()) { - auto length = content_length_header.value().to_uint(); - if (length.has_value()) - content_length = length.value(); - } - - deferred_invoke([this, content_length](auto&) { did_progress(content_length, m_received_size); }); - - if (content_length.has_value()) { - auto length = content_length.value(); - if (m_received_size >= length) { - m_received_size = length; - finish_up(); - return IterationDecision::Break; - } - } - return IterationDecision::Continue; - }); - - if (!is_established()) { -#ifdef JOB_DEBUG - dbgln("Connection appears to have closed, finishing up"); -#endif - finish_up(); - } - }); -} - -void Job::finish_up() -{ - m_state = State::Finished; - if (!m_can_stream_response) { - auto flattened_buffer = ByteBuffer::create_uninitialized(m_received_size); - u8* flat_ptr = flattened_buffer.data(); - for (auto& received_buffer : m_received_buffers) { - memcpy(flat_ptr, received_buffer.data(), received_buffer.size()); - flat_ptr += received_buffer.size(); - } - m_received_buffers.clear(); - - // For the time being, we cannot stream stuff with content-encoding set to _anything_. - auto content_encoding = m_headers.get("Content-Encoding"); - if (content_encoding.has_value()) { - flattened_buffer = handle_content_encoding(flattened_buffer, content_encoding.value()); - } - - m_buffered_size = flattened_buffer.size(); - m_received_buffers.append(move(flattened_buffer)); - m_can_stream_response = true; - } - - flush_received_buffers(); - if (m_buffered_size != 0) { - // We have to wait for the client to consume all the downloaded data - // before we can actually call `did_finish`. in a normal flow, this should - // never be hit since the client is reading as we are writing, unless there - // are too many concurrent downloads going on. - deferred_invoke([this](auto&) { - finish_up(); - }); - return; - } - - auto response = HttpResponse::create(m_code, move(m_headers)); - deferred_invoke([this, response](auto&) { - did_finish(move(response)); - }); -} -} diff --git a/Libraries/LibHTTP/Job.h b/Libraries/LibHTTP/Job.h deleted file mode 100644 index b57b220396..0000000000 --- a/Libraries/LibHTTP/Job.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2020, The SerenityOS developers. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include <AK/FileStream.h> -#include <AK/HashMap.h> -#include <AK/Optional.h> -#include <LibCore/NetworkJob.h> -#include <LibCore/TCPSocket.h> -#include <LibHTTP/HttpRequest.h> -#include <LibHTTP/HttpResponse.h> - -namespace HTTP { - -class Job : public Core::NetworkJob { -public: - explicit Job(const HttpRequest&, OutputStream&); - virtual ~Job() override; - - virtual void start() override = 0; - virtual void shutdown() override = 0; - - HttpResponse* response() { return static_cast<HttpResponse*>(Core::NetworkJob::response()); } - const HttpResponse* response() const { return static_cast<const HttpResponse*>(Core::NetworkJob::response()); } - -protected: - void finish_up(); - void on_socket_connected(); - void flush_received_buffers(); - virtual void register_on_ready_to_read(Function<void()>) = 0; - virtual void register_on_ready_to_write(Function<void()>) = 0; - virtual bool can_read_line() const = 0; - virtual String read_line(size_t) = 0; - virtual bool can_read() const = 0; - virtual ByteBuffer receive(size_t) = 0; - virtual bool eof() const = 0; - virtual bool write(ReadonlyBytes) = 0; - virtual bool is_established() const = 0; - virtual bool should_fail_on_empty_payload() const { return true; } - virtual void read_while_data_available(Function<IterationDecision()> read) { read(); }; - - enum class State { - InStatus, - InHeaders, - InBody, - Trailers, - Finished, - }; - - HttpRequest m_request; - State m_state { State::InStatus }; - int m_code { -1 }; - HashMap<String, String, CaseInsensitiveStringTraits> m_headers; - Vector<ByteBuffer, 2> m_received_buffers; - size_t m_buffered_size { 0 }; - size_t m_received_size { 0 }; - bool m_sent_data { 0 }; - Optional<ssize_t> m_current_chunk_remaining_size; - Optional<size_t> m_current_chunk_total_size; - bool m_can_stream_response { true }; -}; - -} |