编写AWS Lambda Serverless.yml处理程序的正确方法

时间:2019-12-10 10:09:22

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

#!/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()? 我在这方面做错了什么?

2 个答案:

答案 0 :(得分:0)

您可以尝试使用此方法,它使用lambda-api而不是express。语法看起来类似于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

答案 1 :(得分:0)

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

  1. 使用

    创建一个简单的节点项目

    npm init

  2. 安装无服务器软件包

  3. 使用

    生成无服务器文件

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

  4. 安装无服务器脱机软件包

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

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

    无服务器创建-f functionName

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