javascript - 如何使用 Fetch API 获取/设置多个 'Set-Cookie' header ?

标签 javascript cookies fetch fetch-api response-headers

您可能知道,RFC 6265 表示允许有多个名称为 Set-Cookie 的 header 。
但是, Fetch API 不允许这样做,因为它的 Headers 接口(interface)公开的所有方法(包括 get()set()append()entries() 和所有其他方法)都已实现将所有具有相同名称的 header 的值合并到一个用逗号分隔的单个标题。
例如,如果我们这样做:

var headers = new Headers();
headers.append('content-type', 'text/plain');
headers.append('set-cookie', 'test1=v; Max-Age=0');
headers.append('set-cookie', 'test2=v; Max-Age=0');
headers.append('set-cookie', 'test3=v; Max-Age=0');
然后我们尝试使用 set-cookie 读取 get('set-cookie') 值,或者通过使用 headers 迭代 entries() 变量,我们得到:
'set-cookie' : test1=v; Max-Age=0, test2=v; Max-Age=0, test3=v; Max-Age=0
请注意,如果我们尝试读取或操作具有多个同名 header 的现有响应对象(即由可以支持此类允许行为的其他框架创建)的现有响应对象,也会发生相同的错误行为:换句话说,它看起来像 Fetch API完全无法妥善处理这种情况。
现在,虽然某些 header 需要这种行为,例如 Accept ,但大多数浏览器(包括 Chrome 和 Firefox)都无法正确解析 Set-Cookie header ,从而导致未正确设置 cookie。
这是一个已知的错误吗?如果是这种情况,是否有可用的解决方法可以用来克服这个问题?

最佳答案

这是该标准的一个已知“问题”。它实际上是 Fetch API standard 的第一个音符在 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 chose 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.


您可以阅读更多内容,甚至可以在 spec's repo 中提出您自己的问题。 .
已经有一些问题在讨论 Set-Cookie详细的案例:
  • https://github.com/whatwg/fetch/issues/973
  • https://github.com/whatwg/fetch/issues/506
  • https://github.com/whatwg/fetch/issues/189
  • https://lists.w3.org/Archives/Public/www-archive/2016Jan/thread.html

  • 您提到了使用变通方法,但这实际上取决于您的用例。
    该说明提到使用二级结构来处理这些。
    如果您真的想将这些 cookie 存储在 Headers对象,您可以添加自定义 header 来存储它们:
    new Headers([
      ['X-MyOwn-Set-Cookie-1', 'cookie1=value1'],
      ['X-MyOwn-Set-Cookie-2', 'cookie2=value2']
    ]);
    
    显然,这不是标准的可接受解决方案,但也许您的实际考虑可能符合这种折衷方案。

    正如本注释和评论中的@Barmar 所指出的,您通常使用 Set-Cookie从服务器,而不是前端。
    例如设置多个 Set-Cookie 没有问题与 express :
    测试.js
    const express = require('express');
    
    const app = express();
    
    const cookies = [
      { key: 'cookie1', value: 'value1' },
      { key: 'cookie2', value: 'value2' },
    ];
    
    app.get('*', (req, res) => {
      console.log(req.url);
      for (const { key, value } of cookies) {
        res.cookie(key, value, { expires: new Date(Date.now() + 1000 * 60), httpOnly: true });
      }
      res.status(200).send('Success');
    });
    
    app.listen(3000, () => console.log(`Listening on http://localhost:3000/`));
    
    1号航站楼
    $ node test.js
    Listening on http://localhost:3000/
    
    2号航站楼
    $ curl -v http://localhost:3000/
    [...]
    < HTTP/1.1 200 OK
    < X-Powered-By: Express
    < Set-Cookie: cookie1=value1; Path=/; Expires=Tue, 04 Aug 2020 19:45:53 GMT; HttpOnly
    < Set-Cookie: cookie2=value2; Path=/; Expires=Tue, 04 Aug 2020 19:45:53 GMT; HttpOnly
    < Content-Type: text/html; charset=utf-8
    [...]
    

    关于javascript - 如何使用 Fetch API 获取/设置多个 'Set-Cookie' header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63204093/

    相关文章:

    php - 登录时使用 CURL 和 PHP 获取 facebook cookie

    javascript - 将属性对象的选定对象从原型(prototype)插入数组

    cookies - Kubernetes 集群上的粘性 session

    javascript - 是否可以在文本区域中创建某种下拉菜单?

    java - 在javabean getter中设置cookie

    php - PDO 多次获取同一查询

    MySQL 获取时间问题

    grails - Grails/GORM where-clause如何设置fetchMode属性

    javascript - 如何使用日期选择器对第三个文本框中的文本字段求和天数

    Javascript 随机十六进制生成器返回互补色