summaryrefslogtreecommitdiff
path: root/Libraries/LibHTTP
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-12 12:17:30 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-12 12:17:46 +0100
commit13d7c09125f8eec703d0a43a9a87fc8aa08f7319 (patch)
tree70fd643c429cea5c1f9362c2674511d17a53f3b5 /Libraries/LibHTTP
parentdc28c07fa526841e05e16161c74a6c23984f1dd5 (diff)
downloadserenity-13d7c09125f8eec703d0a43a9a87fc8aa08f7319.zip
Libraries: Move to Userland/Libraries/
Diffstat (limited to 'Libraries/LibHTTP')
-rw-r--r--Libraries/LibHTTP/CMakeLists.txt10
-rw-r--r--Libraries/LibHTTP/Forward.h37
-rw-r--r--Libraries/LibHTTP/HttpJob.cpp106
-rw-r--r--Libraries/LibHTTP/HttpJob.h69
-rw-r--r--Libraries/LibHTTP/HttpRequest.cpp195
-rw-r--r--Libraries/LibHTTP/HttpRequest.h83
-rw-r--r--Libraries/LibHTTP/HttpResponse.cpp41
-rw-r--r--Libraries/LibHTTP/HttpResponse.h53
-rw-r--r--Libraries/LibHTTP/HttpsJob.cpp151
-rw-r--r--Libraries/LibHTTP/HttpsJob.h75
-rw-r--r--Libraries/LibHTTP/Job.cpp405
-rw-r--r--Libraries/LibHTTP/Job.h87
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 };
-};
-
-}