cookie-nameが重複した場合の制御

#cookie-nameが重複した場合の制御

新システムと旧システムを並行稼動させる際に、cookie-nameの重複でハマったので備忘録を兼ねて残す

突然ですが問題です。
Q.以下の条件でCookieを発行して、旧システムにアクセスした場合、ブラウザーからは何のCookieが送信されるか。

新システムと旧システムのドメインは以下の通り

- 新システムのURL = new.example@example.com
- 旧システムのURL = old.example@example.com

以下の順序でCookieを発行する

- 旧システムでCookieを発行
  - `set-cookie: name=taro; Domain=old.example@example.com;`
- 新システムでCookieを発行
  - `set-cookie: name=hanako; Domain=.example@example.com;`

旧システムにアクセスする。
この時、ブラウザーから送信されるCookieはどうなるか？

<details><summary>A.</summary><div>

ブラウザーからは両方のCookieが送信される

Request Headersは以下となる
`cookie: name=taro; name=hanako;`

</div></details>

続いての問題です。

以下の順序でCookieを発行する

- CookieをPath付きで発行
  - `set-cookie: age=0; Path=/;`
- CookieをPath付きで発行
  - `set-cookie: age=100; Path=/future;`

システムにアクセスする。
この時、ブラウザーから送信されるCookieはどうなるか？

<details><summary>A.</summary><div>

ブラウザーからは両方のCookieが送信される

Request Headersは以下の通り
cookie: age=100; age=0;

</div></details>

## Cookieはcookie-name, Domain, Pathの組み合わせ毎に保存される

[RFC 6225](https://www.rfc-editor.org/rfc/rfc6265#page-24)の24Pageの11に以下のように記載されています。

```
11. If the cookie store contains a cookie with the same name,
    domain, and path as the newly created cookie:

    1.  Let old-cookie be the existing cookie with the same name,
        domain, and path as the newly created cookie.  (Notice that
        this algorithm maintains the invariant that there is at most
        one such cookie.)

    2.  If the newly created cookie was received from a "non-HTTP"
        API and the old-cookie's http-only-flag is set, abort these
        steps and ignore the newly created cookie entirely.

    3.  Update the creation-time of the newly created cookie to
        match the creation-time of the old-cookie.

    4.  Remove the old-cookie from the cookie store.
```

**cookie-nameとdomainとpathが同じものが存在している場合、古いCookieとして扱い、Cookie storeから削除すると書いてあります。**

## 同一のcookie-nameの送信順序
[RFC 6225](https://www.rfc-editor.org/rfc/rfc6265#page-25)の25Pageの2に以下のように記載されています。

```
The user agent SHOULD sort the cookie-list in the following
    order:

    *  Cookies with longer paths are listed before cookies with
       shorter paths.

    *  Among cookies that have equal-length path fields, cookies with
       earlier creation-times are listed before cookies with later
       creation-times.

    NOTE: Not all user agents sort the cookie-list in this order, but
    this order reflects common practice when this document was
    written, and, historically, there have been servers that
    (erroneously) depended on this order.
```

**CookieのPath属性の値が長いものを先頭に並べて送信する。
また、Path属性の値の長さが同一の場合、作成時間が早いCookieを先頭に並べて送信する。**
慣習的にこの順序でブラウザー側は送信している。
ただし、サーバー側はこの順序に頼るべきではないと記載されています。

実際に、私の以下の環境で検証したところ、上記の順序に従ってCookieが送信されていました。

- Google Chrome (Version 96.0.4664.93 (Official Build) (x86_64)
- Firefox Browser 95.0b12

10年以上前の[stack overflow](https://stackoverflow.com/questions/4056306/how-to-handle-multiple-cookies-with-the-same-name)の質問への回答でも以下のように各種ブラウザーで上記の順序で送信すると記載されているので、順序の信憑性は高そうです。

```
Chrome 63 / Opera 55 / IE11 / Edge 16 / Safari 11 / Firefox 58 And they all seems to handle it correctly that the Cookie with longer path are before the one with shorter path. And in PHP (tested on version 7) it only read the first cookie which is set to the $_COOKIE variable.
```

サーバー側では送信されたCookieのパスやドメインが分からないので、同一のcookie-nameを使用している場合にどちらを優先するか分からないので、どうしても同一のcookie-nameを使いたい場合は値にpath情報やDomain情報を含める必要があります。