Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Fusio | 1,247 | a month ago | 96 | June 05, 2022 | 143 | agpl-3.0 | PHP | |||
Open source API management platform | ||||||||||
Wundergraph | 1,092 | 2 | 19 hours ago | 64 | June 02, 2022 | 23 | apache-2.0 | TypeScript | ||
Serverless API Gateway for GraphQL, REST, gRPC, Kafka and more with a focus on API Composition & Integration. | ||||||||||
Product Apim | 682 | 2 | 3 days ago | 11 | February 17, 2022 | 1,706 | apache-2.0 | Java | ||
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. | ||||||||||
Service Proxy | 398 | 4 | 2 | 2 days ago | 24 | December 31, 2021 | 41 | apache-2.0 | Java | |
API gateway for REST, OpenAPI, GraphQL and SOAP written in Java. | ||||||||||
Graphql2rest | 275 | 21 days ago | 7 | April 01, 2020 | 9 | mit | JavaScript | |||
GraphQL to REST converter: automatically generate a RESTful API from your existing GraphQL API | ||||||||||
Micro Server Own | 202 | 2 years ago | 3 | other | Java | |||||
基于SpringCloud 的微服务,订单,支付,商场(活动),工作流,用户,短信,极光 | ||||||||||
Tenso | 168 | 6 | 6 | a year ago | 537 | October 15, 2021 | bsd-3-clause | JavaScript | ||
Tenso is an HTTP REST API framework | ||||||||||
Zilla | 138 | 18 hours ago | 46 | other | Java | |||||
Zilla is an event-driven API gateway that can extend Apache Kafka to the edge | ||||||||||
Gohan | 110 | 8 months ago | 2 | March 26, 2021 | 50 | other | Go | |||
Gohan is an API Gateway Server written by Go that makes it easy for developers to create and maintain REST-style API | ||||||||||
Grpcjsontranscoder | 68 | 3 years ago | 5 | February 23, 2020 | mit | C# | ||||
A filter which allows a RESTful JSON API client to send requests to .NET web server over HTTP and get proxied to a gRPC service |
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
.
npm
or yarn
.benchmark
script with npm
or yarn
.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;
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 are routes that require authorization for access, and will redirect to authentication end points if needed.
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!
The /assets/*
route is reserved for the HTML browsable interface assets; please do not try to reuse this for data.
Tenso decorates req
with "helpers" such as req.allow
, req.csrf
, req.ip
, req.parsed
, & req.private
. 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 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)
.
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.
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.
Custom renderers can be registered with server.parser('mimetype', fn);
or directly on server.parsers
. The parameters for a renderer are (arg)
.
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 */
}
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!
{
"auth": {
"basic": {
"enabled": true,
"list": ["username:password", ...],
},
"protect": ["/"]
}
}
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 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 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"]
}
}
{
"auth": {
"bearer": {
"enabled": true,
"tokens": ["abc", ...]
},
"protect": ["/"]
}
}
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 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"
}
}
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 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 */
}
}
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
}
Standard log levels are supported, and are emitted to stdout
& stderr
. Stack traces can be enabled.
{
"logging": {
"level": "warn",
"enabled": true,
"stack": true
}
}
The browsable template can be overridden with a custom HTML document.
{
"template": ""
}
The browsable template can load assets from this folder.
{
"static": "/assets"
}
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 can be defined like such:
"/other": (req, res) => req.server.static(req, res);
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({...});
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
-----------------|---------|----------|---------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------
Copyright (c) 2021 Jason Mulligan
Licensed under the BSD-3-Clause license.