Node.js 正在AWS Lambda/Pulumi中等待http请求
我有一个AWS Lambda函数,它可以触发对Google API的https请求。我希望函数是可等待的,这样它就不会立即结束,而是在得到googleapi的响应后才结束。 是的,我知道我为执行死刑付钱,但这不会经常被调用,所以这很好 问题是http请求似乎没有正确启动。永远不会执行回调 通过在Promise中使用setTimeout,我已经确保了async/await按预期工作。因此,问题出在https.request中的某个地方 还请注意,我正在使用Pulumi部署到AWS,因此可能存在一些隐藏的问题。我就是不知道在哪里Node.js 正在AWS Lambda/Pulumi中等待http请求,node.js,amazon-web-services,aws-lambda,pulumi,Node.js,Amazon Web Services,Aws Lambda,Pulumi,我有一个AWS Lambda函数,它可以触发对Google API的https请求。我希望函数是可等待的,这样它就不会立即结束,而是在得到googleapi的响应后才结束。 是的,我知道我为执行死刑付钱,但这不会经常被调用,所以这很好 问题是http请求似乎没有正确启动。永远不会执行回调 通过在Promise中使用setTimeout,我已经确保了async/await按预期工作。因此,问题出在https.request中的某个地方 还请注意,我正在使用Pulumi部署到AWS,因此可能存在一些
相关代码: AWS Lambda,它调用Google API
从“../../config”导入配置;
从“../../interfaces”导入{IUserInfo};
常量https=require('https');
函数sendHttpsRequest(选项:任意):Promise{
log(`sending request to${options.host}`);
log(`Options是${JSON.stringify(Options)}`);
返回新承诺(功能(解决、拒绝){
log(`request to${options.host}已发送一个`);
让body=新数组();
const request=https.request(选项、函数(res:any){
console.log('statusCode:',res.statusCode);
log('headers:',res.headers);
如果(res.statusCode!=200){
拒绝(res.statusCode);
}
res.on('数据',(数据:任意)=>{
log(`body length为${body.length}`);
console.log('数据到达',数据);
body.push(数据);
log('push to array');
log(data.toString());
});
});
request.on('end',()=>{
console.error(‘请求结束’);
//此时,`body`将整个请求正文作为字符串存储在其中
让结果=Buffer.concat(body.toString();
决心(结果);
});
request.on('error',异步(err:error)=>{
console.error('erroorrr',err.stack);
错误('erroorrr请求失败');
拒绝(错误);
});
request.end();
log(`request to${options.host}已被发送到B`);
});
}
/**
*AWS Lambda将在TopMonks域中创建新的Google帐户
*/
导出默认异步函数googleLambdaImplementation(userInfo:IUserInfo){
const payload=JSON.stringify({
“primaryEmail”:userInfo.topmonksEmail,
“姓名”:{
“givenName”:userInfo.firstName,
“familyName”:userInfo.lastName
},
“密码”:config.defaultPassword,
“changePasswordAtNextLogin”:真
});
const resultResponse:响应={
状态代码:200,
正文:“默认响应。这不应返回到用户的
}
log(“通过post请求调用google api”);
试一试{
常量选项={
主持人:“www.googleapis.com”,
路径:'/admin/directory/v1/users',
方法:“POST”,
标题:{
“内容类型”:“应用程序/json”,
“内容长度”:payload.Length.toString()
},
形式:有效载荷
}
const responseFromGoogle=等待发送HttpSreRequest(选项);
log('responseFromGoogle',JSON.stringify(responseFromGoogle));
}
捕捉(错误){
log('调用google api失败,出现错误',错误');
resultResponse.statusCode=503;
resultResponse.body=`为${userInfo.topmonksEmail}创建新Google帐户时出错。`;
返回结果响应;
}
log('requesttogooglesent');
返回结果响应;
}
问题是http请求似乎没有正确启动。永远不会执行回调
我认为这部分问题与(a)可能没有实际发送https请求和(b)没有为https.request
使用正确的回调签名有关。有关这两方面的详细信息,请参阅中的文档
使用节点获取包 以下示例适用于我使用
节点获取:
从“@pulumi/aws”导入*为aws;
从“节点获取”导入获取;
const api=new aws.apigateway.x.api(“api”{
路线:[{
方法:“获取”,路径:“/”,事件处理程序:异步(ev)=>{
const resp=等待获取(“https://www.google.com");
const body=wait resp.text();
返回{
状态代码:各自的状态,
身体:身体,,
}
},
}],
})
export const url=api.url;
Pulumi抱怨说,它类似于“无法序列化本机函数”之类的东西。问题在于节点获取依赖于Symbol.iterator
如评论中所述,一些可能导致这种情况的条件记录在。然而,我看不到任何明确的原因,为什么这段代码会遇到这些限制。可能有关于如何在上面共享的代码段的上下文之外使用此功能的详细信息,从而导致此问题。使用节点获取package@AlešRoubíček我已经试过了。但这是不可能的。Pulumi抱怨说,它类似于“无法序列化本机函数”之类的东西。有问题的部分是节点获取依赖于符号。迭代器捕获本机函数的问题在这里描述,谢谢您的回答。我试图重写我的脚本,但当我使用node fetch时,它仍然会导致“在node fetch的某处使用Symbol.iterator捕获本机函数…bleble…bleble”。关于错误的回拨签名,您是对的。我会更新我的问题。好的,解决了。如果(res.statusCode!=200){reject(res.Status)}
import config from '../../config';
import { IUserInfo } from '../../interfaces';
const https = require('https');
function sendHttpsRequest(options: any): Promise<any> {
console.log(`sending request to ${options.host}`);
console.log(`Options are ${JSON.stringify(options)}`);
return new Promise(function (resolve, reject) {
console.log(` request to ${options.host} has been sent A`);
let body = new Array<Buffer>();
const request = https.request(options, function (res: any) {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
if (res.statusCode != 200) {
reject(res.statusCode);
}
res.on('data', (data: any) => {
console.log(`body length is ${body.length}`);
console.log('data arrived', data);
body.push(data);
console.log('pushed to array');
console.log(data.toString());
});
});
request.on('end', () => {
console.error('Request ended');
// at this point, `body` has the entire request body stored in it as a string
let result = Buffer.concat(body).toString();
resolve(result);
});
request.on('error', async (err: Error) => {
console.error('Errooooorrrr', err.stack);
console.error('Errooooorrrr request failed');
reject(err);
});
request.end();
console.log(` request to ${options.host} has been sent B`);
});
}
/**
* AWS Lambda to create new Google account in TopMonks domain
*/
export default async function googleLambdaImplementation(userInfo: IUserInfo) {
const payload = JSON.stringify({
"primaryEmail": userInfo.topmonksEmail,
"name": {
"givenName": userInfo.firstName,
"familyName": userInfo.lastName
},
"password": config.defaultPassword,
"changePasswordAtNextLogin": true
});
const resultResponse: Response = {
statusCode: 200,
body: 'Default response. This should not come back to users'
}
console.log('Calling google api via post request');
try {
const options = {
host: 'www.googleapis.com',
path: '/admin/directory/v1/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': payload.length.toString()
},
form: payload
}
const responseFromGoogle = await sendHttpsRequest(options);
console.log('responseFromGoogle', JSON.stringify(responseFromGoogle));
}
catch (err) {
console.log('Calling google api failed with error', err);
resultResponse.statusCode = 503;
resultResponse.body = `Error creating new Google Account for ${userInfo.topmonksEmail}.`;
return resultResponse;
}
console.log('request to google sent');
return resultResponse;
}