From 57541f433b7d9c9c6244172800474c3f642c17f9 Mon Sep 17 00:00:00 2001 From: TheFightingCatfish Date: Wed, 11 Aug 2021 06:09:35 +0800 Subject: [PATCH] LibWeb+LibHTTP: Support multiple Set-Cookie response headers --- Userland/Libraries/LibHTTP/Job.cpp | 21 +++++++++++++++++-- Userland/Libraries/LibHTTP/Job.h | 1 + .../Libraries/LibWeb/Loader/FrameLoader.cpp | 12 ++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibHTTP/Job.cpp b/Userland/Libraries/LibHTTP/Job.cpp index 0bdbc4c6be..237ef81a00 100644 --- a/Userland/Libraries/LibHTTP/Job.cpp +++ b/Userland/Libraries/LibHTTP/Job.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -179,8 +180,11 @@ void Job::on_socket_connected() if (m_state == State::Trailers) { return finish_up(); } else { - if (on_headers_received) + if (on_headers_received) { + if (!m_set_cookie_headers.is_empty()) + m_headers.set("Set-Cookie", JsonArray { m_set_cookie_headers }.to_string()); on_headers_received(m_headers, m_code > 0 ? m_code : Optional {}); + } m_state = State::InBody; } @@ -216,7 +220,20 @@ void Job::on_socket_connected() return deferred_invoke([this] { 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("Set-Cookie")) { + dbgln_if(JOB_DEBUG, "Job: Received Set-Cookie header: '{}'", value); + m_set_cookie_headers.append(move(value)); + return; + } + if (auto existing_value = m_headers.get(name); existing_value.has_value()) { + StringBuilder builder; + builder.append(existing_value.value()); + builder.append(','); + builder.append(value); + m_headers.set(name, builder.build()); + } else { + 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 :( dbgln_if(JOB_DEBUG, "Content-Encoding {} detected, cannot stream output :(", value); diff --git a/Userland/Libraries/LibHTTP/Job.h b/Userland/Libraries/LibHTTP/Job.h index cbb1b640b3..b3caadefeb 100644 --- a/Userland/Libraries/LibHTTP/Job.h +++ b/Userland/Libraries/LibHTTP/Job.h @@ -56,6 +56,7 @@ protected: State m_state { State::InStatus }; int m_code { -1 }; HashMap m_headers; + Vector m_set_cookie_headers; Vector m_received_buffers; size_t m_buffered_size { 0 }; size_t m_received_size { 0 }; diff --git a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp index 60d8a7be45..b226b3054b 100644 --- a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -294,10 +295,15 @@ void FrameLoader::resource_did_load() return; } - // FIXME: Support multiple instances of the Set-Cookie response header. auto set_cookie = resource()->response_headers().get("Set-Cookie"); - if (set_cookie.has_value()) - document->set_cookie(set_cookie.value(), Cookie::Source::Http); + if (set_cookie.has_value()) { + auto set_cookie_json_value = MUST(JsonValue::from_string(set_cookie.value())); + VERIFY(set_cookie_json_value.type() == JsonValue::Type::Array); + for (const auto& set_cookie_entry : set_cookie_json_value.as_array().values()) { + VERIFY(set_cookie_entry.type() == JsonValue::Type::String); + document->set_cookie(set_cookie_entry.as_string(), Cookie::Source::Http); + } + } if (!url.fragment().is_empty()) browsing_context().scroll_to_anchor(url.fragment());