From 267d6d230a7b4c907c1981b825f3f319caa43d60 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Fri, 29 Oct 2021 18:23:40 +0200 Subject: [PATCH 01/14] Add special handling of `set-cookie` to Headers --- fetch.bs | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/fetch.bs b/fetch.bs index 92c09c30b..71cc13e28 100644 --- a/fetch.bs +++ b/fetch.bs @@ -732,12 +732,29 @@ a header list list, run these steps:

For each name in names:

    -
  1. Let value be the result of getting name - from list. +

  2. If name is "set-cookie", then: + +

      +
    1. Let values be a list of all headers in list whose + name is a byte-case-insensitive match for name, in order. + +

    2. For each value of values: + +

        +
      1. Append (name, value) to headers. +

      +
    -
  3. Assert: value is not null. +

  4. Otherwise: -

  5. Append (name, value) to headers. +

      +
    1. Let value be the result of getting name + from list. + +

    2. Assert: value is not null. + +

    3. Append (name, value) to headers. +

  • Return headers. @@ -5966,12 +5983,17 @@ interface Headers { }; -

    Unlike a header list, a {{Headers}} object cannot represent more than one -`Set-Cookie` header. In a way this is problematic as unlike all other -headers `Set-Cookie` headers cannot be combined, but since `Set-Cookie` -headers are not exposed to client-side JavaScript this is deemed an acceptable compromise. -Implementations could choose the more efficient {{Headers}} object representation even for a -header list, as long as they also support an associated data structure for +

    Unlike a header list, a {{Headers}} object combines the values of +multiple headers of the same name into a single header value. This is problematic for the +`Set-Cookie` header, as unlike all other headers it can not be safely combined. For +client-side JavaScript this is not very problematic, as the platform never exposes +`Set-Cookie`. This can be problematic for server-side runtimes that do expose this +header. Because of this there is some special handling for the `Set-Cookie` header in +the implementation of the {{Headers}} interface: `Set-Cookie` headers are not +concatenated when they are returned from the {{Headers}} iterator. This means that specifically for +this header, multiple tuples of the same name can be returned. Implementations could choose the more +efficient {{Headers}} object representation even for a header list, as long as they +also support an associated data structure for `Set-Cookie` headers.

    A {{Headers}} object has an associated From f837d20096872e4e5ac917178fac573c765568ca Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Fri, 29 Oct 2021 18:17:57 +0200 Subject: [PATCH 02/14] Add getSetCookie() --- fetch.bs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fetch.bs b/fetch.bs index 71cc13e28..9c053e638 100644 --- a/fetch.bs +++ b/fetch.bs @@ -5977,6 +5977,7 @@ interface Headers { undefined append(ByteString name, ByteString value); undefined delete(ByteString name); ByteString? get(ByteString name); + sequence<ByteString> getSetCookie(); boolean has(ByteString name); undefined set(ByteString name, ByteString value); iterable<ByteString, ByteString>; @@ -6040,6 +6041,9 @@ new Headers(meta2);

    Returns as a string the values of all headers whose name is name, separated by a comma and a space. +

    headers . getSetCookie() +

    Returns a list of the values for all headers whose name is set-cookie. +

    headers . has(name)

    Returns whether there is a header whose name is name. @@ -6182,6 +6186,14 @@ method steps are to append (name, value header list. +

    The getSetCookie() method steps are: + +

      +
    1. Return values of all headers in this's + header list whose name is a byte-case-insensitive match + for `set-cookie`, in order. +

    +

    The has(name) method steps are:

      From 7c79f92e51e1a39080090d1426e20ac071055101 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 10:26:45 +0100 Subject: [PATCH 03/14] Update fetch.bs Co-authored-by: Steven --- fetch.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fetch.bs b/fetch.bs index 9c053e638..50e6895dc 100644 --- a/fetch.bs +++ b/fetch.bs @@ -5986,7 +5986,7 @@ interface Headers {

      Unlike a header list, a {{Headers}} object combines the values of multiple headers of the same name into a single header value. This is problematic for the -`Set-Cookie` header, as unlike all other headers it can not be safely combined. For +`Set-Cookie` header, as unlike all other headers, it cannot be safely combined. For client-side JavaScript this is not very problematic, as the platform never exposes `Set-Cookie`. This can be problematic for server-side runtimes that do expose this header. Because of this there is some special handling for the `Set-Cookie` header in From 8176492569841e7885970fbc736faaae77d7d67a Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 11:27:45 +0100 Subject: [PATCH 04/14] review comment Co-authored-by: Anne van Kesteren --- fetch.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fetch.bs b/fetch.bs index 50e6895dc..a215f0d7f 100644 --- a/fetch.bs +++ b/fetch.bs @@ -6042,7 +6042,7 @@ new Headers(meta2); comma and a space.

      headers . getSetCookie() -

      Returns a list of the values for all headers whose name is set-cookie. +

      Returns a list of the values for all headers whose name is `Set-Cookie`.

      headers . has(name)

      Returns whether there is a header whose name is name. From 93e26a388b569aaf36183db4c99f4f3bf195bd14 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 11:29:15 +0100 Subject: [PATCH 05/14] review comment Co-authored-by: Anne van Kesteren --- fetch.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fetch.bs b/fetch.bs index a215f0d7f..ca0a4b0f0 100644 --- a/fetch.bs +++ b/fetch.bs @@ -732,7 +732,7 @@ a header list list, run these steps:

      For each name in names:

        -
      1. If name is "set-cookie", then: +

      2. If name is `set-cookie`, then:

        1. Let values be a list of all headers in list whose From 07e6f8c32f72ccffe71d9a460eb5dcf9d09a57c1 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 11:29:36 +0100 Subject: [PATCH 06/14] typo Co-authored-by: Anne van Kesteren --- fetch.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fetch.bs b/fetch.bs index ca0a4b0f0..ddc76f008 100644 --- a/fetch.bs +++ b/fetch.bs @@ -5977,7 +5977,7 @@ interface Headers { undefined append(ByteString name, ByteString value); undefined delete(ByteString name); ByteString? get(ByteString name); - sequence<ByteString> getSetCookie(); + sequence<ByteString> getSetCookie(); boolean has(ByteString name); undefined set(ByteString name, ByteString value); iterable<ByteString, ByteString>; From e82d2155f642a973c5b54918cb2dd75560378b5c Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 11:42:40 +0100 Subject: [PATCH 07/14] add empty list case --- fetch.bs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fetch.bs b/fetch.bs index ddc76f008..16ef970c3 100644 --- a/fetch.bs +++ b/fetch.bs @@ -6189,9 +6189,12 @@ method steps are to append (name, value

          The getSetCookie() method steps are:

            -
          1. Return values of all headers in this's +

          2. If list does not contain `Set-Cookie`, then + return an empty list. + +

          3. Return the values of all headers in this's header list whose name is a byte-case-insensitive match - for `set-cookie`, in order. + for `Set-Cookie`, in order.

          The has(name) method steps are: From 0394f8e2cf005718e9e211392bf6efffc3de4898 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 11:47:57 +0100 Subject: [PATCH 08/14] update note regarding set-cookie --- fetch.bs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fetch.bs b/fetch.bs index 16ef970c3..da1ae3f3a 100644 --- a/fetch.bs +++ b/fetch.bs @@ -5986,15 +5986,16 @@ interface Headers {

          Unlike a header list, a {{Headers}} object combines the values of multiple headers of the same name into a single header value. This is problematic for the -`Set-Cookie` header, as unlike all other headers, it cannot be safely combined. For -client-side JavaScript this is not very problematic, as the platform never exposes -`Set-Cookie`. This can be problematic for server-side runtimes that do expose this -header. Because of this there is some special handling for the `Set-Cookie` header in -the implementation of the {{Headers}} interface: `Set-Cookie` headers are not -concatenated when they are returned from the {{Headers}} iterator. This means that specifically for -this header, multiple tuples of the same name can be returned. Implementations could choose the more -efficient {{Headers}} object representation even for a header list, as long as they -also support an associated data structure for +`Set-Cookie` header, as unlike all other headers, it cannot be safely combined. Because +of this, there is some special handling for the `Set-Cookie` header in +the implementation of the {{Headers}} interface, just like in the HTTP spec. +`Set-Cookie` headers are not concatenated when they are returned from the {{Headers}} +iterator, and there is a +headers . getSetCookie() method +to retrieve the list of all `Set-Cookie`, ordered and uncombined. This means that +specifically for this header, multiple tuples of the same name can be returned from the {{Headers}} +iterator. Implementations could choose the more efficient {{Headers}} object representation even for +a header list, as long as they also support an associated data structure for `Set-Cookie` headers.

          A {{Headers}} object has an associated From 538c3601a1ac0b865e2348884d0bb37a597a79db Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 11:52:49 +0100 Subject: [PATCH 09/14] fix --- fetch.bs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fetch.bs b/fetch.bs index da1ae3f3a..53992dd78 100644 --- a/fetch.bs +++ b/fetch.bs @@ -735,8 +735,9 @@ a header list list, run these steps:

        2. If name is `set-cookie`, then:

            -
          1. Let values be a list of all headers in list whose - name is a byte-case-insensitive match for name, in order. +

          2. Let values be a list of all values of + headers in list whose name is a + byte-case-insensitive match for name, in order.

          3. For each value of values: From 84a1afc1d4ae62a46941ec05f347ff59d964148a Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 1 Nov 2021 13:35:27 +0100 Subject: [PATCH 10/14] review comment Co-authored-by: Andreu Botella --- fetch.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fetch.bs b/fetch.bs index 53992dd78..b1ae1688b 100644 --- a/fetch.bs +++ b/fetch.bs @@ -6191,7 +6191,7 @@ method steps are to append (name, value

            The getSetCookie() method steps are:

              -
            1. If list does not contain `Set-Cookie`, then +

            2. If this's header list does not contain `Set-Cookie`, then return an empty list.

            3. Return the values of all headers in this's From e95ce2915bbafd54e4814f8696c1e460048a2668 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Thu, 4 Nov 2021 14:38:36 +0100 Subject: [PATCH 11/14] fix formatting --- fetch.bs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fetch.bs b/fetch.bs index 9c053e638..47e7012a7 100644 --- a/fetch.bs +++ b/fetch.bs @@ -736,9 +736,10 @@ a header list list, run these steps:

              1. Let values be a list of all headers in list whose - name is a byte-case-insensitive match for name, in order. + name is a byte-case-insensitive match for name, in order. -

              2. For each value of values: +

              3. +

                For each value of values:

                1. Append (name, value) to headers. From 3e7013c502149fbae5009fa09f7408c3410f9d1a Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Sun, 30 Jan 2022 21:10:35 +0100 Subject: [PATCH 12/14] linting --- fetch.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fetch.bs b/fetch.bs index cd5bca37d..1fd446808 100644 --- a/fetch.bs +++ b/fetch.bs @@ -733,7 +733,7 @@ a header list list, run these steps:

                  1. If name is `set-cookie`, then: - +

                    1. Let values be a list of all values of headers in list whose name is a @@ -741,7 +741,7 @@ a header list list, run these steps:

                    2. For each value of values: - +

                      1. Append (name, value) to headers.

                      From 90feab8360e2e310988cc4a6cd0e4324db598260 Mon Sep 17 00:00:00 2001 From: Andreu Botella Date: Mon, 6 Feb 2023 14:04:59 +0100 Subject: [PATCH 13/14] Move and rewrite implementation note of Headers and header lists. --- fetch.bs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/fetch.bs b/fetch.bs index 9236e799c..aae108a68 100644 --- a/fetch.bs +++ b/fetch.bs @@ -572,7 +572,10 @@ uses the more colloquial term "header". [[HTTP]] headers. It is initially « ».

                      A header list is essentially a specialized multimap: an ordered list of -key-value pairs with potentially duplicate keys. +key-value pairs with potentially duplicate keys. Since headers other than `Set-Cookie` +are always combined when exposed to client-side JavaScript, implementations could choose a more +efficient representation, as long as they also support an associated data structure for +`Set-Cookie` headers.

                      To @@ -6524,20 +6527,6 @@ interface Headers { }; -

                      Unlike a header list, a {{Headers}} object combines the values of -multiple headers of the same name into a single header value. This is problematic for the -`Set-Cookie` header, as unlike all other headers, it cannot be safely combined. Because -of this, there is some special handling for the `Set-Cookie` header in -the implementation of the {{Headers}} interface, just like in the HTTP spec. -`Set-Cookie` headers are not concatenated when they are returned from the {{Headers}} -iterator, and there is a -headers . getSetCookie() method -to retrieve the list of all `Set-Cookie`, ordered and uncombined. This means that -specifically for this header, multiple tuples of the same name can be returned from the {{Headers}} -iterator. Implementations could choose the more efficient {{Headers}} object representation even for -a header list, as long as they also support an associated data structure for -`Set-Cookie` headers. -

                      A {{Headers}} object has an associated header list (a header list), which is initially empty. This From 9e950f1192784621203e67fdeaf3e568f2a529d8 Mon Sep 17 00:00:00 2001 From: Andreu Botella Date: Mon, 6 Feb 2023 16:50:29 +0100 Subject: [PATCH 14/14] Formatting fixes --- fetch.bs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/fetch.bs b/fetch.bs index aae108a68..47093bc87 100644 --- a/fetch.bs +++ b/fetch.bs @@ -894,7 +894,8 @@ directly. Use get, decode, and split instead.

                      For each name of names:

                        -
                      1. If name is `set-cookie`, then: +

                      2. +

                        If name is `set-cookie`, then:

                        1. Let values be a list of all values of @@ -909,15 +910,16 @@ directly. Use get, decode, and split instead.

                      -
                    3. Otherwise: +

                    4. +

                      Otherwise:

                        -
                      1. Let value be the result of getting name - from list. +

                      2. Let value be the result of getting name + from list. -

                      3. Assert: value is non-null. +

                      4. Assert: value is non-null. -

                      5. Append (name, value) to headers. +

                      6. Append (name, value) to headers.

                    @@ -6744,8 +6746,8 @@ method steps are to append (name, value

                    The getSetCookie() method steps are:

                      -
                    1. If this's header list does not contain `Set-Cookie`, then - return an empty list. +

                    2. If this's header list does not contain + `Set-Cookie`, then return « ».

                    3. Return the values of all headers in this's header list whose name is a byte-case-insensitive match