在 Lambda 函数中使用 axios 时设置先前请求的 cookie

Drk*_*Str 9 node.js aws-lambda axios

我在 NodeJs 应用程序中使用 Axios 来执行 HTTP 请求。

我使用 post 请求登录,不需要在标头中设置 cookie。

const instance = axios.create({ baseURL: 'https://some_url.com' , withCredentials: true});
const response = await instance.post('auth/login', data);
Run Code Online (Sandbox Code Playgroud)

这会set-cookie在其标头中返回一个我需要在所有后续 API 调用中使用的标头。这是我为此尝试过的代码。

const getResponse = await instance.get('/getStuff?$top=10', { withCredentials: true });
Run Code Online (Sandbox Code Playgroud)

这总是返回“未登录错误”。我无权访问服务器,但我假设这是因为我的获取请求没有在其标头中发送 cookie。

在 lambda 中运行所有这些,不确定这是否会产生影响。

问题:如何从第一个请求中获取 cookie并在我的请求post中使用它?get

hlf*_*rmn 17

withCredentials选项适用于axios的浏览器版本,并依赖浏览器来存储当前站点的 cookie。

由于您在 Node 中使用它,因此您必须自己处理存储。

TL;DR 登录请求后,将 cookie 保存在某处。在发送其他请求之前,请确保包含该 cookie。

要读取 cookie,请检查response.headers对象,该对象应该有一个set-cookie标头(这就是所有 cookie 的真正含义 - 带有一些特殊约定的标头,这些约定已演变成某种标准)。

要在 HTTP 请求中包含 cookie,请设置cookie标头。


一般示例

如果您需要比“保存这个我知道我会得到的简单 cookie”更好的东西,您也可以寻找一些“cookie 处理”库。

// 1. Get your axios instance ready
function createAxios() {
    const axios = require('axios');
    return axios.create({withCredentials: true});
}
const axiosInstance = createAxios();

// 2. Make sure you save the cookie after login.
// I'm using an object so that the reference to the cookie is always the same.
const cookieJar = {
    myCookies: undefined,
};

async function login() {
    const response = await axiosInstance.post('http://localhost:3003/auth', {});
    cookieJar.myCookies = response.headers['set-cookie'];
}

// 3. Add the saved cookie to the request.
async function request() {
    // read the cookie and set it in the headers
    const response = await axiosInstance.get('http://localhost:3003',
        {
            headers: {
                cookie: cookieJar.myCookies,
            },
        });
    console.log(response.status);
}

login()
    .then(() => request());
Run Code Online (Sandbox Code Playgroud)

您还可以axios.defaults在获得 cookie 后对所有请求强制执行该 cookie:

async function login() {
    const response = await axios.post('http://localhost:3003/auth', {});
    axios.defaults.headers.cookie = response.headers['set-cookie']
}

async function request() {
    const response = await axios.get('http://localhost:3003');
}
Run Code Online (Sandbox Code Playgroud)

只要你能保证login之前打电话request就没有问题。

您还可以探索其他 axios 功能,例如拦截器。这可能有助于将所有与“axios config”相关的代码保留在一个位置(而不是摆弄函数中的默认值或调整和login中的 cookie )。loginrequest


拉姆达

AWS Lambda 可能会为其收到的每个请求生成一个新实例,因此您可能需要注意一些实例生命周期详细信息。

您的选择是:

  1. 什么都不做:您不关心为每个 lambda 运行发送“登录请求”。它不会对您的响应时间产生太大影响,并且其他 api 不介意您发送多个登录请求。另外,其他 api 也没有问题,因为您可能同时有多个 cookie(例如,如果 10 个 lambda 实例同时登录)。

  2. lambda 实例中的缓存:您有一个 lambda 实例,每隔一段时间就会使用一次,但通常您在任何时间都不会运行多个实例。您只是出于性能原因才想缓存 cookie。如果多个 lambda 实例正在运行,它们每个都会获得一个 cookie。请注意其他 api 不允许多次登录。

    如果这是您所需要的,请确保将 axios 配置放入单独的模块中并导出配置的实例。它将在该 lambda 实例的运行之间进行缓存。此选项非常适合拦截器的使用。

    const instance = axios.create({...});
    instance.interceptors.response.use(() => {}); /* persist the cookie */
    instance.interceptors.request.use(() => {}); /* set the cookie if you have one */
    export default instance;
    
    Run Code Online (Sandbox Code Playgroud)
  3. lambda 实例之间的缓存:这稍微复杂一些。您将需要在外部缓存 cookie。您可以将其存储在数据库中(键值存储、关系型、面向文档的 - 无关紧要),或者您可以尝试使用共享磁盘空间(我相信 lambda 实例共享一些目录,例如/tmp,但不是 100% 确定)。

    您可能必须处理这样的情况:您的 lambda 同时受到多个请求的影响,并且它们都认为自己没有 cookie,因此它们都尝试同时登录。基本上就是常见的分布式系统/缓存问题。