npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2021 – Pkg Stats / Ryan Hefner

lambda-serverless-api

v9.1.3

Published

Basic Api Wrapper for Serverless Framework.

Downloads

2,376

Readme

Rest Abstraction for Serverless API

Build Status Test Coverage Dependabot Status Dependencies NPM Downloads Semantic-Release Gardener

Middleware for AWS Lambda and Api Gateway.

Provides support for:

  • Fully customizable parameter types
  • Support for header, json, query and context, parameter positions
  • Abstraction for text, json, and binary response types
  • Full support for custom authentication
  • Full support for cors
  • Full support for versioning and deprecation
  • Automatic generation of Swagger documentation
  • Rate limiting using in-memory or S3
  • Access and error logging using lambda-monitor

Install

$ npm install --save lambda-serverless-api

Getting Started

Define api and handlers in handler.js as follows:

const api = require('lambda-serverless-api').Api({/* options */});

api.wrap('POST register', [
  api.Str('name', 'json', { required: false }),
  api.Email('email', 'json'),
  api.Str('password', 'json')
], /* options, */ ({ name, email, password }) => {
  // handle registration logic here ...
  if (new Date().getHours() === 4) {
    throw api.ApiError('I am a teapot', 418);
  }
  return api.JsonResponse({ message: 'Success!' });
});

module.exports = api;

then hook the router endpoint into the Serverless Framework configuration as

functions:
  router:
    handler: handler.router
    events:
      - schedule: rate(10 minutes)
      - http:
          path: /{proxy+}
          method: ANY

Api Options

The api is plugin based and all options are tied to plugins. The following plugins are customizable:

  • cors: Used to handle CORS Option requests as well as injecting CORS headers into responses
  • versioning: Used to declare valid api version and handle deprecation
  • logger: Log responses to console (CloudWatch), which can then be picked up by lambda-monitor
  • preValidation: Hook to allow pre-validation (e.g. authentication)
  • rateLimit: Used for rate limiting
  • router: Used to modify the router, e.g. set a custom route prefix
  • robots: Used to modify robots.txt response
  • responseHeaders: Used to inject certain predefined response headers, such as Date
  • preLogic: Used to e.g. modify parameters after they are parsed

Please see implementation for details.

Endpoint Definition: wrap()

Takes the following positional arguments:

  • route string: The method and the uri of the format ${method} ${uri}
  • params Array<Parameter>: Parameter definitions
  • options: Endpoint options (optional)
  • handler function: The handler using parsed parameters as the first argument

Note: The (slightly modified) original event and context can be accessed as additional handler parameters

Api Parameters

There are various pre-defined parameters available

  • Bool: Boolean input
  • IsoDate: Date input as YYYY-MM-DD
  • Email: Email input
  • Enum: Enum input
  • FieldsParam: String input that gets parsed as object-fields
  • GeoPoint: GPS coordinate input
  • GeoPoly: GPS coordinate of polygon input and holes
  • GeoPolyList: List of GPS coordinate of polygon input and holes
  • GeoRect: GPS coordinate rectangle input
  • GeoShape: GPS coordinate polygon input
  • GeoShapeList: GPS coordinate polygon list input
  • Int: Integer input
  • IntShort: Short Integer input
  • IsoTimestamp: Iso timestamp input
  • Json: Json input that has to conform to Joi schema
  • Json-list: List of Json input that has to conform to Joi schema
  • List: List input
  • NumberList: Number list input
  • NumberParam: Number input
  • Regex: String input that has to conform to a regex
  • Str: String input
  • StrList: String list input
  • UUID: Uuid input

Parameter Types

There are four types of parameter types:

  • json: parsed from the json request body
  • query: parsed from the query string
  • header: parsed from the header and case insensitive
  • context: parsed from the lambda event context. Useful to e.g. obtain the client IP

Parameter Options

Below are the default parameter options. Most parameters have several customization options. Please see implementation for details.

required

Allow input to be not present

Type: boolean Default: true

nullable

Allow input value to be null. Note: Parameter position must be in [json, context]

Type: boolean Default: false

getter

Experimental

Note: only recommended for advanced use cases. Optionally asynchronous custom "getting" of variables. Getter function takes raw input from event, IE a query parameter will always pass String values into the getter function. Warnings:

  • If used with { nullable: true }, if a rawInput is passed as null, or if a non-required parameter is not sent, the getter function will not be used.
  • Some params (such as Bool, Int, Json, etc) do extra processing after the getter function has returned, and may return inconsistent results. Thorough testing is recommended.

Takes unresolved parameters as second parameter. Simple parameters can be accessed directly, unresolved can be resolved by using await.

Type: Function Default: null

Example

/* { "name": "  John   "} */
module.exports = api.wrap('POST name', [
  api.Str('name', 'json', true, { getter: (input, params) => input.trim() })
], ({ name }) => {
  console.log(name); // "John"
});

Parameter Names

Parameter names are converted to camel case when passed into the handler.

E.g. the header X-Custom-Header would be passed as xCustomHeader.

Api Response

There are two types of api responses: Success and error responses. Error responses need to be thrown, while success responses need to be returned from the endpoint handler. The following responses are available:

  • Success: ApiResponse (e.g. for plain text), JsonResponse (for json), BinaryResponse (e.g. for images)
  • Failure: ApiError

Success responses take the positional parameters data (required), statusCode (optional) and headers (optional).

Error responses take the positional parameters message (required), statusCode (optional), messageId (optional) and context (optional). They are always of Json format. It is recommended that an easily identifiable messageId is set on all error responses.

Please see implementation for details.

Rate Limiting

Done globally through the API configuration. However can be overwritten on a per-endpoint basis by specifying limit as an integer in the endpoint definition option.

Rate limiting uses memory by default, which is not shared across function containers. However one can configure S3 to share the rate limiting (recommended). This will (1) increase latency and (2) increase costs per api call.

By default the client IP (['requestContext.identity.sourceIp']) is used for rate limiting. However this can be customized.

General Notes

Each endpoint definition can also be exposed as a separate lambda function. However this is not recommended for larger APIs due to CloudFormation limitations (maximum number of resources and stack invalidation issues).

Consider using yaml-boost for loading Serverless Framework configuration.

Consider using a single router function instead of declaring each function individually.

Swagger Documentation

To generate swagger documentation we can call api.generateSwagger() after the api is initialized with routes. For merge-overwrite the swagger definition fs.smartWrite() can be used.

Example

const fs = require('smart-fs');
const path = require('path');

const updateSwagger = async () => {
  const swaggerFile = path.join(__dirname, '..', 'swagger.yml');
  const swaggerContent = await api.generateSwagger();
  const result = fs.smartWrite(swaggerFile, swaggerContent);
  expect(result, 'Swagger file updated').to.equal(false);
};
updateSwagger();

Logging Api Errors / Exceptions

To monitor api errors and exceptions, lambda-monitor should be configured with rollbar.