All Projects → avoidwork → Tenso

avoidwork / Tenso

Licence: bsd-3-clause
Tenso is an HTTP REST API framework

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Tenso

Tree Gateway
This is a full featured and free API Gateway
Stars: ✭ 160 (-4.19%)
Mutual labels:  api, microservices, microservice, api-gateway, gateway
Gravitee Gateway
Gravitee.io - API Management - OpenSource API Gateway
Stars: ✭ 1,123 (+572.46%)
Mutual labels:  api, microservices, api-gateway, gateway
Dubbo Go Pixiu
Based on the proxy gateway service of dubbo-go, it solves the problem that the external protocol calls the internal Dubbo cluster. At present, it supports HTTP and gRPC[developing].
Stars: ✭ 124 (-25.75%)
Mutual labels:  microservices, microservice, api-gateway, gateway
Up
Up focuses on deploying "vanilla" HTTP servers so there's nothing new to learn, just develop with your favorite existing frameworks such as Express, Koa, Django, Golang net/http or others.
Stars: ✭ 8,439 (+4953.29%)
Mutual labels:  api, microservices, microservice, api-gateway
Product Apim
Welcome to the WSO2 API Manager source code! For info on working with the WSO2 API Manager repository and contributing code, click the link below.
Stars: ✭ 508 (+204.19%)
Mutual labels:  rest, microservices, api-gateway, gateway
Goku Api Gateway
A Powerful HTTP API Gateway in pure golang!Goku API Gateway (中文名:悟空 API 网关)是一个基于 Golang开发的微服务网关,能够实现高性能 HTTP API 转发、服务编排、多租户管理、API 访问权限控制等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行 API 服务治理、提高 API 服务的稳定性和安全性。
Stars: ✭ 2,773 (+1560.48%)
Mutual labels:  api, microservices, api-gateway, gateway
Manba
HTTP API Gateway
Stars: ✭ 3,000 (+1696.41%)
Mutual labels:  api, microservice, api-gateway, gateway
Fusio
Open source API management platform
Stars: ✭ 946 (+466.47%)
Mutual labels:  api, rest, microservice, api-gateway
Go Restful Api
An idiomatic Go REST API starter kit (boilerplate) following SOLID principles and Clean Architecture
Stars: ✭ 1,043 (+524.55%)
Mutual labels:  api, rest, microservice
Falcon
The no-nonsense REST API and microservices framework for Python developers, with a focus on reliability, correctness, and performance at scale.
Stars: ✭ 8,654 (+5082.04%)
Mutual labels:  api, rest, microservices
Graphql Microservices
Showcasing a graphql microservice setup
Stars: ✭ 68 (-59.28%)
Mutual labels:  api, microservices, microservice
Mini Platform
Mini-Platform致力于更简洁易用的轻量级微服务治理平台。
Stars: ✭ 45 (-73.05%)
Mutual labels:  microservices, microservice, gateway
Hgw
hgw是由gateway网关服务、manager控制服务构成的一套轻量级网关系统。目前支持http/https协议的服务控制
Stars: ✭ 81 (-51.5%)
Mutual labels:  microservices, api-gateway, gateway
Altair
Lightweight and Robust API Gateway written in Go
Stars: ✭ 34 (-79.64%)
Mutual labels:  api, microservice, api-gateway
Practical Clean Ddd
A simplified and effortless approach to get started with Domain-driven Design, Clean Architecture, CQRS, and Microservices patterns
Stars: ✭ 28 (-83.23%)
Mutual labels:  microservices, microservice, cqrs
Health Checks Api
Standardize the way services and applications expose their status in a distributed application
Stars: ✭ 78 (-53.29%)
Mutual labels:  api, microservices, microservice
Event Sourcing Jambo
An Hexagonal Architecture with DDD + Aggregates + Event Sourcing using .NET Core, Kafka e MongoDB (Blog Engine)
Stars: ✭ 159 (-4.79%)
Mutual labels:  microservices, microservice, cqrs
Apisix Docker
the docker for Apache APISIX
Stars: ✭ 119 (-28.74%)
Mutual labels:  api, microservices, api-gateway
Gemini
Model Driven REST framework to automatically generate CRUD APIs
Stars: ✭ 138 (-17.37%)
Mutual labels:  rest, microservices, microservice
Kong
🦍 The Cloud-Native API Gateway
Stars: ✭ 30,838 (+18365.87%)
Mutual labels:  microservices, microservice, api-gateway

Tenso

build status

Tenso is an HTTP REST API framework, that will handle the serialization & creation of hypermedia links; all you have to do is give it Arrays or Objects.

Benchmark

  1. Clone repository from GitHub.
  2. Install dependencies with npm or yarn.
  3. Execute benchmark script with npm or yarn.

Example

Creating an API with Tenso can be this simple:

const path = require('path'),
    app = require("tenso")({routes: require(path.join(__dirname, "routes.js"))});

module.exports = app;

Creating Routes

Routes are loaded as a module, with each HTTP method as an export, affording a very customizable API server.

You can use res to res.send(body[, status, headers]), res.redirect(url), or res.error(status[, Error]).

The following example will create GET routes that will return an Array at /, an Error at /reports/tps, & a version 4 UUID at /uuid.

As of 10.3.0 you can specify always as a method to run middleware before authorization middleware, which will skip always middleware registered after it (via instance methods).

const uuid = require("tiny-uuid4");

module.exports.get = {
	"/": ["reports", "uuid"],
	"/reports": ["tps"],
	"/reports/tps": (req, res) => res.error(785, Error("TPS Cover Sheet not attached")),
	"/uuid": (req, res) => res.send(uuid(), 200, {"cache-control": "no-cache"})
};

Protected Routes

Protected routes are routes that require authorization for access, and will redirect to authentication end points if needed.

Unprotected Routes

Unprotected routes are routes that do not require authorization for access, and will exit the authorization pipeline early to avoid rate limiting, csrf tokens, & other security measures. These routes are the DMZ of your API! You must secure these end points with alternative methods if accepting input!

Reserved Route

The /assets/* route is reserved for the HTML browsable interface assets; please do not try to reuse this for data.

Request Helpers

Tenso decorates req with "helpers" such as req.ip, & req.parsed. PATCH, PUT, & POST payloads are available as req.body. Sessions are available as req.session when using local authentication.

Tenso decorates res with "helpers" such as res.send(), res.status(), & res.json().

Responses

Responses will have a standard shape, and will be utf-8 by default. The result will be in data. Hypermedia (pagination & links) will be in links:[ {"uri": "...", "rel": "..."}, ...], & also in the Link HTTP header.

Page size can be specified via the page_size parameter, e.g. ?page_size=25.

Sort order can be specified via then order-by which accepts [field ]asc|desc & can be combined like an SQL 'ORDER BY', e.g. ?order_by=desc or ?order_by=lastName%20asc&order_by=firstName%20asc&order_by=age%20desc

{
  "data": "`null` or ?",
  "error": "`null` or an `Error` stack trace / message",
  "links": [],
  "status": 200
}

Final modifications can be made to a response body after hypermedia() by overriding tenso.final(req, res, body).

REST / Hypermedia

Hypermedia is a prerequisite of REST, and is best described by the Richardson Maturity Model. Tenso will automagically paginate Arrays of results, or parse Entity representations for keys that imply relationships, and create the appropriate Objects in the link Array, as well as the Link HTTP header. Object keys that match this pattern: /_(guid|uuid|id|uri|url)$/ will be considered hypermedia links.

For example, if the key user_id was found, it would be mapped to /users/:id with a link rel of related.

Tenso will bend the rules of REST when using authentication strategies provided by passport.js, or CSRF if is enabled, because they rely on a session. Session storage is in memory, or Redis. You have the option of a stateless or stateful API.

Hypermedia processing of the response body can be disabled as of 10.2.0, by setting req.hypermedia = false via middleware.

Browsable API / Renderers / Serializers

Tenso 1.4.0 added a few common format renderers, such as CSV, HTML, YAML, & XML. The HTML interface is a browsable API! You can use it to verify requests & responses, or simply poke around your API to see how it behaves.

Custom renderers can be registered with server.renderer('mimetype', fn); or directly on server.renderers. The parameters for a renderer are (req, res, arg). Custom serializes can be registered with server.serializer('mimetype', fn); or directly on server.serializers. The parameters for a serializer are (arg, err, status = 200, stack = false); if arg is null then err must be an Error & stack determines if the response body is the Error.message or Error.stack property.

Parsers

Custom renderers can be registered with server.parser('mimetype', fn); or directly on server.parsers. The parameters for a renderer are (arg).

Configuration

This is a sample configuration for Tenso, without authentication or SSL. This would be ideal for development, but not production! Enabling SSL is as easy as providing file paths for the two keys.

{
	"auth": { /* Optional, see Authentication section */
		"delay": 0 /* Random delay on authorization validation */
	},
	"cacheSize": 1000, /* Optional, size of Etag & route LRU caches */
	"cacheTTL": 0, /* Optional, TTL of items in Etag & route LRU caches */
	"headers": {}, /* Optional, custom headers */
	"hostname": "localhost", /* Optional, default is 'localhost' */
	"index": ["index.htm", "index.html"], /* Files served when accessing a static assets folder */
	"json": 0, /* Optional, default indent for 'pretty' JSON */
	"logging": {
		"level": "info", /* Optional */
		"enabled": true, /* Optional */
		"stack": false, /* Optional */
		"stackWire": false /* Optional */
	},
	"corsExpose": "x-custom-header, x-custom-header-abc",
	"origins": ["*"], /* Optional, allowed origins of CORS requests */
	"port": 8000, /* Optional */
	"routes": require("./routes.js"), /* Required! */
	"regex": {
		"hypermedia": "[a-zA-Z]+_(guid|uuid|id|url|uri)$", /* Optional, changes hypermedia detection / generation */
		"id": "^(_id|id)$" /* Optional, changes hypermedia detection / generation */
	},
	"session": { /* Optional */
		"secret": null,
		"store": "memory", /* "memory" or "redis" */
		"redis": {} /* See connect-redis for options */
	},
	"ssl": { /* Optional */
		"cert": null,
		"key": null
	},
	"renderHeaders": true, /* false will disable headers in HTML interface */
	"title": "My API", /* Page title for browsable API */
	"uid": 33 /* Optional, system account uid to drop to after starting with elevated privileges to run on a low port */
}

Authentication

The protect Array is the endpoints that will require authentication. The redirect String is the end point users will be redirected to upon successfully authenticating, the default is /.

Sessions are used for non Basic or Bearer Token authentication, and will have /login, /logout, & custom routes. Redis is supported for session storage.

Multiple authentication strategies can be enabled at once.

Authentication attempts have a random delay to deal with "timing attacks"; always rate limit in production environment!

Basic Auth

{
	"auth": {
		"basic": {
			"enabled": true,
			"list": ["username:password", ...],
		},
		"protect": ["/"]
	}
}

JWT

JWT (JSON Web Token) authentication is stateless and does not have an entry point. The auth(token, callback) function must verify token.sub, and must execute callback(err, user).

This authentication strategy relies on out-of-band information for the secret, and other optional token attributes.

{
	"auth": {
		"jwt": {
			"enabled": true,
			"auth": function (token, cb) { ... }, /* Authentication handler, to 'find' or 'create' a User */
			"algorithms": [], /* Optional signing algorithms, defaults to ["HS256", "HS384", "HS512"] */
			"audience": "", /* Optional, used to verify `aud` */
			"issuer: "", /* Optional, used to verify `iss` */
			"ignoreExpiration": false, /* Optional, set to `true` to ignore expired tokens */
			"scheme": "Bearer", /* Optional, set to specify the `Authorization` scheme */
			"secretOrKey": ""
		}
		"protect": ["/private"]
	}
}

Local

Local authentication will create /login. auth(username, password) must execute callback(err, user).

{
	"auth": {
		"local": {
			"enabled": true,
			"auth": function ( ... ) { ... }, /* Authentication handler, to 'find' or 'create' a User */
		}
		"protect": ["/private"]
	}
}

OAuth2

OAuth2 authentication will create /auth, /auth/oauth2, & /auth/oauth2/callback routes. auth(accessToken, refreshToken, profile, callback) must execute callback(err, user).

{
	"auth": {
		"oauth2": {
			"enabled": true,
			"auth": function ( ... ) { ... }, /* Authentication handler, to 'find' or 'create' a User */
			"auth_url": "", /* Authorization URL */
			"token_url": "", /* Token URL */
			"client_id": "", /* Get this from authorization server */
			"client_secret": "" /* Get this from authorization server */
		},
		"protect": ["/private"]
	}
}

Oauth2 Bearer Token

{
	"auth": {
		"bearer": {
			"enabled": true,
			"tokens": ["abc", ...]
		},
		"protect": ["/"]
	}
}

SAML

SAML authentication will create /auth, /auth/saml, & /auth/saml/callback routes. auth(profile, callback) must execute callback(err, user).

Tenso uses passport-saml, for configuration options please visit it's homepage.

{
	"auth": {
		"saml": {
			"enabled": true,
			...
		},
		"protect": ["/private"]
	}
}

Sessions

Sessions can use a memory (default) or redis store. Memory will limit your sessions to a single server instance, while redis will allow you to share sessions across a cluster of processes, or machines. To use redis, set the store property to "redis".

If the session secret is not provided, a version 4 UUID will be used.

{
	"session" : {
		cookie: {
			httpOnly: true,
			path: "/",
			sameSite: true,
			secure: false
		},
		name: "tenso.sid",
		proxy: true,
		redis: {
			host: "127.0.0.1",
			port: 6379
		},
		rolling: true,
		resave: true,
		saveUninitialized: true,
		secret: "tensoABC",
		store: "memory"
	}
}

Security

Tenso uses lusca for security as a middleware. Please see it's documentation for how to configure it; each method & argument is a key:value pair for security.

{
	"security": { ... }
}

Rate Limiting

Rate limiting is controlled by configuration, and is disabled by default. Rate limiting is based on token, session, or ip, depending upon authentication method.

Rate limiting can be overridden by providing an override function that takes req & rate, and must return (a modified) rate.

{
	"rate": {
		"enabled": true,
		"limit": 450, /* Maximum requests allowed before `reset` */
		"reset": 900, /* TTL in seconds */
		"status": 429, /* Optional HTTP status */
		"message": "Too many requests",  /* Optional error message */
		"override": function ( req, rate ) { ... } /* Override the default rate limiting */
	}
}

Limiting upload size

A 'max byte' limit can be enforced on all routes that handle PATCH, POST, & PUT requests. The default limit is 20 KB (20480 B).

{
	"maxBytes": 5242880
}

Logging

Standard log levels are supported, and are emitted to stdout & stderr. Stack traces can be enabled.

{
	"logging": {
		"level": "warn",
		"enabled": true,
		"stack": true
	}
}

Template

The browsable template can be overridden with a custom HTML document.

{
    "template": ""
}

Static assets folder

The browsable template can load assets from this folder.

{
    "static": "/assets"
}

Static assets cache

The browsable template assets have a default public cache of 300 seconds (5 minutes). These assets will always be considered public, but you can customize how long they are cacheable.

{
    "staticCache": 300
}

Custom static routes

Custom static routes can be defined like such:

   "/other": (req, res) => req.server.static(req, res);

EventSource streams

Create & cache an EventSource stream to send messages to a Client. See tiny-eventsource for configuration options:

const streams = new Map();

...

"/stream": (req, res) => {
 const id = req.user.userId;

 if (streams.has(id) === false) {
   streams.set(id, req.server.eventsource({ms: 3e4), "initialized");
 }

 streams.get(id).init(req, res);
}

...

// Send data to Clients
streams.get(id).send({...});

Testing Code Coverage

Run the coverage script with npm or yarn.

-----------------|---------|----------|---------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------
File             | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------------|---------|----------|---------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------
All files        |   79.05 |     69.1 |   66.18 |   78.81 |                                                                                                                                                       
 tenso           |      80 |    63.16 |      50 |      80 |                                                                                                                                                       
  index.js       |      80 |    63.16 |      50 |      80 | 21-24,33-34,53-54                                                                                                                                     
 tenso/lib       |      79 |    69.35 |   66.42 |   78.75 |                                                                                                                                                       
  base.js        |    22.5 |      100 |   17.86 |    22.5 | 6-30,44-58,68-76,86-94                                                                                                                                
  middleware.js  |   89.86 |    77.36 |   83.33 |   91.18 | 13-14,43-44,87,132                                                                                                                                    
  parsers.js     |   58.33 |        0 |      50 |   58.33 | 12-19                                                                                                                                                 
  regex.js       |     100 |      100 |     100 |     100 |                                                                                                                                                       
  renderers.js   |    97.3 |    68.75 |   93.33 |     100 | 10-19,35,41-48,58                                                                                                                                     
  serializers.js |     100 |    55.56 |     100 |     100 | 6-16                                                                                                                                                  
  shared.js      |      40 |    33.33 |      50 |      40 | 8-11                                                                                                                                                  
  tenso.js       |   73.39 |    53.62 |      65 |    72.9 | 167-168,181-191,199-206,248-249,262,296-298,306-312,322-341                                                                                           
  utility.js     |   83.33 |    74.37 |   81.13 |   82.97 | 34,46-49,53,72,118-120,137-138,147-148,152-153,187,203,207,218-219,228,236,238,249-250,271,301,315-337,339-361,382,388-392,438-439,498,543,567,629-630
-----------------|---------|----------|---------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------

License

Copyright (c) 2021 Jason Mulligan

Licensed under the BSD-3-Clause license.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].