简体   繁体   English

在 AWS Lambda / Pulumi 中等待 http 请求

[英]Awaiting http request in AWS Lambda / Pulumi

I have an AWS Lambda function which triggers https request to Google API.我有一个 AWS Lambda 函数,它触发对 Google API 的 https 请求。 I want the function to be awaitable, so that it does not end immediately, but only after getting response from Google API.我希望该函数是可等待的,这样它就不会立即结束,而是在从 Google API 得到响应之后才结束。 Yes, I know I pay for the execution, but this will not be called often, so it is fine.是的,我知道我为执行付费,但不会经常调用,所以没问题。

The problem is that the http request does not seem to fire correctly.问题是 http 请求似乎没有正确触发。 The callback is never executed.回调永远不会执行。

I have made sure that the async/await works as expected by using setTimeout in a Promise.我已经通过在 Promise 中使用 setTimeout 来确保 async/await 按预期工作。 So the issue is somewhere in the https.request.所以问题出在 https.request 中的某个地方。

Also note that I am using Pulumi to deploy to AWS, so there might be some hidden problem in there.另请注意,我使用 Pulumi 部署到 AWS,因此其中可能存在一些隐藏问题。 I just can't figure out where.我就是想不通在哪里。


The relevant code:相关代码:

AWS Lambda which calls the Google API调用 Google API 的 AWS Lambda

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;
 }

The problem is that the http request does not seem to fire correctly.问题是 http 请求似乎没有正确触发。 The callback is never executed.回调永远不会执行。

I believe this part of the issue is related to some combination of (a) potentially not actually sending the https request and (b) not using the correct callback signature for https.request .我相信这部分问题与 (a) 可能实际上没有发送 https 请求和 (b) 没有为https.request使用正确的回调签名的https.request See the documentation at https://nodejs.org/api/https.html#https_https_request_options_callback for details on both of these.有关这两者的详细信息,请参阅https://nodejs.org/api/https.html#https_https_request_options_callback上的文档。

Use node-fetch package使用 node-fetch 包

The following example works for me using node-fetch :以下示例适用于我使用node-fetch

import * as aws from "@pulumi/aws";
import fetch from "node-fetch";

const api = new aws.apigateway.x.API("api", {
    routes: [{
        method: "GET", path: "/", eventHandler: async (ev) => {
            const resp = await fetch("https://www.google.com");
            const body = await resp.text();
            return {
                statusCode: resp.status,
                body: body,
            }
        },
    }],
})

export const url = api.url;

Pulumi complains, it something like "Can not serialize native function" or something like that. Pulumi 抱怨说,它类似于“无法序列化本机功能”之类的东西。 The problematic part is that node-fetch relies on Symbol.iterator有问题的部分是 node-fetch 依赖于 Symbol.iterator

As noted in the comments, some of the conditions that can lead to this are documented at https://pulumi.io/reference/serializing-functions.html .正如评论中所指出的,可能导致这种情况的一些条件记录在https://pulumi.io/reference/serializing-functions.html 中 However, I don't see any clear reason why this code would hit any of those limitations.但是,我看不出为什么此代码会遇到任何这些限制的任何明确原因。 There may be details of how this is used outside the context of the snippet shared above which lead to this.可能有关于如何在上面共享的代码段的上下文之外使用它的详细信息,这导致了这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM