node.js - 在 Lambda 函数中使用 axios 时根据先前的请求设置 cookie
问题描述
我在我的 NodeJs 应用程序中使用 Axios 来执行 HTTP 请求。
我正在使用不需要在标头中设置 cookie 的发布请求登录。
const instance = axios.create({ baseURL: 'https://some_url.com' , withCredentials: true});
const response = await instance.post('auth/login', data);
这将set-cookie
在其标头中返回一个,我需要在所有后续 API 调用中使用它。这是我为此尝试过的代码。
const getResponse = await instance.get('/getStuff?$top=10', { withCredentials: true });
这总是返回“未登录错误”。我无权访问服务器,但我假设这是因为我的 get 请求没有在其标头中发送 cookie。
在 lambda 中运行所有这些,不确定这是否会有所不同。
问题:如何从我的第一个请求中获取 cookiepost
并在我的请求中使用它get
?
解决方案
该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());
一旦你得到它,你也可以使用它axios.defaults
来对所有请求强制执行 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');
}
只要你能保证你login
之前打电话request
,你会没事的。
您还可以探索其他 axios 功能,例如拦截器。这可能有助于将所有与“axios config”相关的代码保存在一个地方(而不是摆弄函数中的默认值或同时调整和中的login
cookie )。login
request
拉姆达
AWS Lambda 可能会为其收到的每个请求生成一个新实例,因此您可能需要注意一些实例生命周期的详细信息。
您的选择是:
什么都不做:你不关心每次运行 lambda 时发送一个“登录请求”。它不会对您的响应时间产生太大影响,并且其他 api 也不介意您发送多个登录请求。此外,其他 api 对您可能同时拥有多个 cookie 没有问题(例如,如果 10 个 lambda 实例同时登录)。
在 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;
lambda 实例之间的缓存:这稍微复杂一些。您需要在外部缓存 cookie。您可以将它存储在数据库中(键值存储、关系、面向文档 - 没关系),或者您可以尝试使用共享磁盘空间(我相信 lambda 实例共享一些目录,例如
/tmp
,但不是 100% 确定)。您可能必须处理您的 lambda 同时被多个请求击中并且他们都认为他们没有 cookie,因此他们都尝试同时登录的情况。基本上,常见的分布式系统/缓存问题。
推荐阅读
- java - Android开发:ID在变量中时如何访问字符串?
- ios - Object Swift 中的 Array 中的对象
- java - 自定义类型?如果我们可以这么说
- java - 在不断退出的 docker 容器中安装自定义包
- python-3.x - 在 Jupyter 中向 nbconvert 原始单元格添加语法高亮
- browser-cache - 注销后,当单击返回按钮时,由于 october cms 中的缓存问题,会出现安全的上次访问页面。如何防止这种情况?
- twilio - Twilio 音频输出问题
- python - Jupyter notebook,使用数据进行机器学习
- python - 不断消除数据点,直到获得良好的相关系数
- php - 如何在foreach循环中添加html?