【问题标题】:Correct way to write the Handler for AWS Lambda Serverless.yml为 AWS Lambda Serverless.yml 编写处理程序的正确方法
【发布时间】:2020-04-03 11:50:18
【问题描述】:
#!/usr/bin/env node
const server = require('./Helpers/server');

const app = {};
/**
 * Initiating the Server.
 */
app.init = () => {
   server.init();
};
app.init();
module.exports = app;

我有这个启动服务器的 index.js 文件。

/**
 * dependencies:
 * @type {module:http}:
 */
const http = require('http');
const url = require('url');
const config = require('./config');
const StringDecoder = require('string_decoder').StringDecoder;
const router = require('./../Helpers/routing');
const generator = require('./../Services/generator');
const validator = require('./../Helpers/validator');
const printer = require('./../Helpers/printer');
const constants = require('./constants');
const Cookies = require('cookies');
const server = {};
/**
 * Core Server logic for parsing and choosing the handlers.
 * @param req: the Request object.
 * @param res: The Response object.
 */
server.unifiedServer = function (req, res) {
   const parsedUrl = url.parse(req.url, true);
   const pathName = parsedUrl.pathname;
   const path = pathName.replace(/^\/+|\/+$/g, '');
   const firstRoute = path.split("/")[0];
   const secondPath = path.substr(path.indexOf("/") + 1);
   const method = req.method.toLowerCase();
   const queryString = parsedUrl.query;
   const decoder = new StringDecoder('utf-8');
   const header = req.headers['content-type'];
   const cookie = new Cookies(req, res);
   const chosenHandler = router.getPath(firstRoute);
   let postData = "";
   let handlerData;
   if (header === 'application/octet-stream') {
      let data = [];
      req.on('data', d => {
         data.push(d);
      }).on('end', () => {
         const buffer = Buffer.concat(data);
         handlerData = {
            path: secondPath,
            method,
            queryString,
            data: buffer
         };
         execHandlers(handlerData);
      });
   } else {
      req.on('data', function (data) {
         postData += decoder.write(data);
      }).on('end', () => {
         postData += decoder.end();
         postData = generator.generateParsedJSON(postData);
         handlerData = {
            path: secondPath,
            method,
            queryString,
            postData
         };
         execHandlers(handlerData);
      });
   }

   /**
    * Method to send the response back to the client.
    * @param responseData: The response data to be send.
    * @param statusCode: The status code that to be send.
    * @param cookies: The array containing the cookies.
    */
   function sendResponse(responseData, statusCode, cookies) {
      responseData = validator.validateUndefined(responseData) ? responseData : {};
      statusCode = validator.validateNumber(statusCode) ? statusCode : 500;
      responseData = JSON.stringify(responseData);
      try {
         if (validator.validateUndefined(cookies)) {
            for (let i = 0; i < cookies.length; i++) {
               const oneCookie = cookies[i];
               printer.printHighlightedLog(oneCookie);
               cookie.set(oneCookie[constants.COOKIE_KEY], oneCookie[constants.COOKIE_VALUE]);
            }
         }
         res.setHeader(constants.CONTENT_TYPE_TEXT, constants.CONTENT_TYPE_JSON);
         res.writeHead(statusCode, constants.HEADERS);
         res.end(responseData);
         printer.printHighlightedLog("RETURNING: " + responseData + "FOR PATH: " + handlerData.path);
      } catch (e) {
         printer.printError(e);
      }
   }

   /**
    * Method to execute the Handlers.
    * @param handlerData: The request object after parsing it.
    */
   function execHandlers(handlerData) {
      if (handlerData.method === 'options') {
         sendResponse({}, 200);
      } else {
         let promise = chosenHandler(handlerData);
         promise.then((responseObject) => {
            sendResponse(responseObject[0], responseObject[1], responseObject[2]);
         }).catch(err => {
            sendResponse(err[0], err[1], err[2]);
         });
      }
   }
};
//TODO: Add the HTTPS Server.
/**
 * Method to create the Server.
 */
server.httpServer = http.createServer((req, res) => {
   server.unifiedServer(req, res);
});
/**
 * Initializing the server.
 */
server.init = () => {
   /**
    * Method to listen on the port.
    */
   server.httpServer.listen(config.port, () => {
      console.log("Server Listening on Port ", config.port);
   });
};
/**
 * exporting the server module.
 */
module.exports = server;

这是我的 Server.js 应用程序。

#serverless.yml

service: serverless-nodejs-app

provider:
  name: aws
  runtime: nodejs10.x
  stage: dev
  region: ap-south-1

functions:
  app:
    handler: index.app # reference the file and exported method
    events: # events trigger lambda functions
      - http: # this is an API Gateway HTTP event trigger
          path: /
          method: ANY
          cors: true
      - http: # all routes get proxied to the Express router
          path: /{proxy+}
          method: ANY
          cors: true

这是我的 serverless.yml。

{
    "errorType": "Runtime.ImportModuleError",
    "errorMessage": "Error: Cannot find module 'app'",
    "stack": [
        "Runtime.ImportModuleError: Error: Cannot find module 'app'",
        "    at _loadUserApp (/var/runtime/UserFunction.js:100:13)",
        "    at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)",
        "    at Object.<anonymous> (/var/runtime/index.js:45:30)",
        "    at Module._compile (internal/modules/cjs/loader.js:778:30)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)",
        "    at Module.load (internal/modules/cjs/loader.js:653:32)",
        "    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:585:3)",
        "    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)",
        "    at startup (internal/bootstrap/node.js:283:19)"
    ]
}

这是错误消息。

我想知道为 Serverless.yml 编写处理程序的正确方法是什么。 我不想使用快递。如何从 serverless.yml 调用我的 index.js-> app.init()? 我在这做错了什么?

【问题讨论】:

  • 工人和服务器的目的是什么?
  • Server 是我创建 HTTPServer 的文件。你现在可以忽略的工人。
  • 你为什么要创建一个http服务器
  • 因为我正在尝试创建一个 HTTP 服务器,以便我的 API 可以监听传入的请求。
  • 为什么不按常规方式,在 serverless.yml 中定义端点,每个 lambda 一个处理函数

标签: node.js amazon-web-services aws-lambda serverless


【解决方案1】:

你可以试试这个,它使用lambda-api 而不是快递。语法看起来类似于 express。但我没用过这个。看看它。

# Functions
functions:
  serverless-api-sample:
    name: ${self:service}-${self:provider.stage}-serverless-api-sample
    handler: handler.router
    timeout: 30
    events:
      - http:
          path: 'v1/{proxy+}'
          method: any

lambda 代码

const app = require('lambda-api')({ version: 'v1.0', base: 'v1' })
app.put('/posts/:post_id', (req,res) => {
  res.status(200).json({
    params: req.params
  })
})

参考:

https://www.jeremydaly.com/build-serverless-api-serverless-aws-lambda-lambda-api/ https://github.com/jeremydaly/lambda-api

【讨论】:

  • “帮助”键是做什么用的?为什么是 index.handler?
  • 对不起,我的函数名,让我重命名
  • 处理程序是handler.ts 文件。
  • 我还没有这样做,但是这个方法可以让我们定义一个 lambda 来服务多个端点
【解决方案2】:

我可以看到您正在尝试使用 express 在 lambda 中创建服务器,这是错误的。 如果你想创建无服务器项目,

  1. 使用

    创建一个简单的节点项目

    npm init

  2. 安装无服务器包

  3. 使用

    生成无服务器文件

    无服务器创建 --template aws-nodejs

  4. 安装无服务器离线包

  5. 在插件下的 serverless.yml 中添加其引用

  6. 在 serverless.yml 中创建函数如下

    无服务器创建 -f 函数名

您的函数已准备就绪。 您可以使用命令serverless offline 离线运行项目 现在,您可以点击 serverless.yml 中的函数下提到的 URI 来测试您的 lambda 函数。

【讨论】:

  • 不,你错了,我正在尝试使用 AWS Lambda 而不使用 Express 创建 NodeJs 服务器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-24
  • 2017-09-21
  • 2011-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多