Bladeren bron

LibWeb+LibHTTP: Support multiple Set-Cookie response headers

TheFightingCatfish 4 jaren geleden
bovenliggende
commit
57541f433b

+ 19 - 2
Userland/Libraries/LibHTTP/Job.cpp

@@ -5,6 +5,7 @@
  */
 
 #include <AK/Debug.h>
+#include <AK/JsonArray.h>
 #include <LibCompress/Gzip.h>
 #include <LibCompress/Zlib.h>
 #include <LibCore/Event.h>
@@ -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<u32> {});
+                    }
                     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);

+ 1 - 0
Userland/Libraries/LibHTTP/Job.h

@@ -56,6 +56,7 @@ protected:
     State m_state { State::InStatus };
     int m_code { -1 };
     HashMap<String, String, CaseInsensitiveStringTraits> m_headers;
+    Vector<String> m_set_cookie_headers;
     Vector<ByteBuffer, 2> m_received_buffers;
     size_t m_buffered_size { 0 };
     size_t m_received_size { 0 };

+ 9 - 3
Userland/Libraries/LibWeb/Loader/FrameLoader.cpp

@@ -5,6 +5,7 @@
  */
 
 #include <AK/Debug.h>
+#include <AK/JsonArray.h>
 #include <AK/LexicalPath.h>
 #include <AK/SourceGenerator.h>
 #include <LibGemini/Document.h>
@@ -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());