Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/codeofnode/bulkapi

Combine multiple APIs into single, call each API, and return a set of responses.
https://github.com/codeofnode/bulkapi

api bulk-api handler modular-components multiple restful

Last synced: 28 days ago
JSON representation

Combine multiple APIs into single, call each API, and return a set of responses.

Awesome Lists containing this project

README

        

# BulkAPI
Combine multiple APIs into single, call each API, and return a set of responses.

## Why it exists?
> Let's take an example of web service. At startup web service client need to fetch of loads of data from server.
And of course, you server should have a loads of modular component, each of which are responsible to return a part of data.
Now certainly we don't like to make a separate HTTP/Network or similar request to fetch from single component,
of course because we don't like to face `X` times network/handshaking overheads.
What we want is to setup another single endpoint that would be responsible to return a set of data in one go.

`bulkapi` simplifies that single endpoint you need to setup, and let the whole service behave purely on modular components.

It accept the payload in a `certain` format, and divide into set of `x` requests and call each of them to handler.
Once response from each handler is recieved, it combines the result into particular format and return to client.

## Why should you use it.
* Reduce Network Layer Overheads
* The server's endpoints to handle are very robust, modular, and unitified. Now you can focus on units.
* Code Logic of server becomes very simple
* You may generate some request body payload, programmatically (in format of BulkAPI's CoreBody) So you request can become totally dynamic

## Install
```
npm install bulkapi
```

## How to use
### On server side
```javascript
const BulkAPI = require('bulkapi'), HTTP = require('http');

const bulkapi = new BulkAPI.default(
// this is your `custom` handler that will be called for all APIs that you define inside bulkAPI payload
// this ideally should be server's entry point, but you may tweek as per your need
function(reqObj, resObj){
// _setupRequest is restify's server method. Some init stuffs for a request.
server._setupRequest(reqObj, resObj);
// _hander is restify's server method. restify routes to a particular handler with this method call.
server._handle(reqObj, resObj);
},
// you may also pass you custom IncomingMessage and/or ServerResponse `class`
HTTP.IncomingMessage, HTTP.ServerResponse);

restifyOrExpressServer.post('/bulkapi', bodyParser, bulkapi.callbulk.bind(bulkapi));
```
### On client side
```javascript
// Type CoreBody
/**
* The CoreBody type definition
* @typedef {Object} CoreBody
* @property {object} base - the base object. used to setup some default values in all APIs
* @property {string} base.url - if exists the base.url will be prefixed to request url, and the final url will be formed
* @property {object} base.headers - if exists the base.headers will be extended to request headers as default header pairs
* @property {array} from - the source from which the bulk api should be generated
* if the length of result evaluated `from` is `x` then there will be `x` bulk API calls in a request
* evaluating and cloning the template `_` x times and pushing as a request.
* @property {CoreReq[]|CoreReq} _ - the set of bulk requests (if array),
* or a template (if object), with `from`
* The final result should be a set of requests in type of CoreReq
*/
// Type CoreReq
/**
* The CoreReq type definition
* @typedef {Object} CoreReq
* @property {string} [url] - the url to call, ref to req.url
* @property {object} [headers] - the key value map of headers, ref to req.headers
* @property {object|object[]|CoreBody} [body] - the request payload, ref to req.body
* (body if your req instance has payload access from key `body`, ie as express or restify or json2server has)
* It may further contain any kind of payload.
* It can also have nested bulkapi call at any number of levels.
* If so it should again have object in form of CoreBody
* where url/method is should be used that is used to mount BulkAPI instance
* Please note that bodyParser will have no significance to body of nested BulkAPI calls
* @property {string} [method] - the method ie GET, POST etc, ref to req.method
* it is optional, if method not found then its body become the static init values
* so that some static values can be used later on for as variable
* eg at later stage {{result.{{someIndex}}}} will get the value found `someIndex`ed API from
* the list of APIs of bulk payload
* @property {boolean} [first] - whether we need to obtain result of any request at init, prior
* should be used when the result of API need to be evaluated that should be used in upcoming API calls
*/
```
#### Example of a simple client request
```javascript
{
url: 'bulkapi', // main http request end point, that will be handled by BulkAPI.callbulk
method: 'POST', // main http request method
// main http request payload, this should be stringified before sending as main request,
// and should be parsed at server end, in form of object
body: {
base: {
url: this.baseurl, // this will be prefixed to all request url's
},
_: [
{
url: '/getSomething?rank=1', // CoreReq request url,
method: 'GET',
}, {
url: '/createSomehing', // CoreReq request url,
method: 'POST',
body: { // Some sample request payload, remember this need not be parsed, will be automatically available
name: 'A',
rank: 1,
}
}, {
// result will be an array of results that is being available from responses.
// So result.0 refers to first response (of request /getSomething)
// So result.0.id refers to the FirstResponseObject.id
url: '/updateSomehing/{{result.0.id}}',
method: 'PUT',
body: { // Some sample request payload, remember this need not be parsed
name: 'A',
rank: 2,
},
},
],
},
}
```

#### A Complex Nested Example
```javascript
{
url: 'bulkapi', // main http request end point, that will be handled by BulkAPI.callbulk
method: 'POST', // main http request method
// main http request payload
body: [{
body: SomeStaticArrayOfEndpoints,
}, {
// nested request url, that will be handled custom handler passed to BulkAPI instance
url: `${this.baseurl}bulkapi`,
method: 'POST',
body: {
from: SomeStaticArrayEndpoints,
base: {
url: this.baseurl,
},
_: { // as `_` is object here, it is the template for SomeStaticArray iterations
url: 'bulkapi', // deep nested request url, will again be handled custom hander of BulkAPI instance
method: 'POST',
body: {
base: {
url: this.baseurl,
},
_: [{
url: '{{$data}}', // $data is the current item of SomeStaticArrayEndpoints
method: 'GET',
first: true, // we need response this this api call first, before rest of the calls
}, {
url: 'bulkapi',
method: 'POST',
body: {
// result of first call, with endpoint {{$data}}, accessing output property of response object
// assuming the above request send response of object, where output is key having array of some data
from: '{{result.0.output}}',
base: {
// rootResult is the result of main HTTP root request.
// So here rootResult.0 is the first response of main request
// means rootResult.0 = SomeStaticArrayEndpoints
// means rootResult.0.{{$}} = the current endpoint being evaluated (same as {{$data}} used above)
url: `${this.baseurl}{{rootResult.0.{{$}}}}/`,
},
_: { // this is the template for `{{result.0.output}}` array
// here {{data}} is used of the LATEST `from` evaluation that is from `{{result.0.output}}`
url: '{{$data}}',
method: 'GET',
},
},
}],
},
},
},
}],
}
```

#### Example of a BulkAPI response
> the Response is always an array. Each item in array will be the response of corresponding participating request calls (CoreReq calls). The same rule applies to nested BulkAPI calls too.

### Use of Templist
> You may use the variables in any format, even function calls, as described in [Templist](https://github.com/codeofnode/templist)

## Roadmap
> Raise a feature request by logging an [issue](https://github.com/codeofnode/bulkapi/issues), and that will fill this place

## Any hurdles?
> Found anything difficult to understand? or some bug or some improvement?. Create an issue [issue](https://github.com/codeofnode/bulkapi/issues) for the same.

## License

BulkAPI is released under the MIT license:

http://www.opensource.org/licenses/MIT