Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/mosasiru/lua-resty-jsonrpc-batch

JSONRPC batch protocol module for OpenResty / ngx_lua
https://github.com/mosasiru/lua-resty-jsonrpc-batch

Last synced: about 2 months ago
JSON representation

JSONRPC batch protocol module for OpenResty / ngx_lua

Awesome Lists containing this project

README

        

# lua-resty-jsonrpc-batch

The Lua-Openresty implementation of [JSON-RPC 2.0](http://www.jsonrpc.org/specification) Batch Request (http://www.jsonrpc.org/specification#batch).

The batch request is non-blocking and proceeded paralelly because this module makes use of location.capture_multi of ngx_lua. So the performance is high while the implementation is simple.

This module parses a batch request, validate it, and makes multi subrequest to upstream servers.
Note that you must have a upstream JSON-RPC server as you like, but upstream servers need not apply for JSON-RPC batch request.

## Installation

```
luarocks --local install lua-resty-jsonrpc-batch
```

## Synopsis

### Basic Usage

```lua
server {
location /api {
# jsonrpc endpoint
}
location /api/batch {
lua_need_request_body on;

content_by_lua '
local jsonrpc_batch = require "resty.jsonrpc.batch"
client = jsonrpc_batch:new()
local res, err = client:batch_request({
path = "/api",
request = ngx.var.request_body,
})
if err then
ngx.exit(500)
end
ngx.say(res)
';
}
}
```

### Advanced Usage

```lua
http {

init_by_lua '
local jsonrpc_batch = require "resty.jsonrpc.batch"
client = jsonrpc_batch.new({
-- make limitation to batch request array size
max_batch_array_size = 10,
-- for logging upstream response time
before_subrequest = function(self, ctx, req)
ctx.start_at = ngx.now()
end,
after_subrequest = function(self, ctx, resps, req)
ngx.var.jsonrpc_upstream_response_time = ngx.now() - ctx.start_at
end,
})
';

server {
set $jsonrpc_upstream_response_time -;

location ~ /api/method/.* {
# jsonrpc endpoint
}

location /api/batch {
lua_need_request_body on;

content_by_lua '
local res, err = client:batch_request({
-- you can change the endpoint per request
path = function(self, ctx, req)
return "/api/method/" .. req.method
end,
request = ngx.var.request_body,
});
if err then
ngx.log(ngx.CRIT, err);
ngx.exit(500);
end
ngx.say(res);
';
}
}
}

```

## Methods

### new
`usage:client = jsonrpc_batch:new(options)`

The options argument is a Lua table holding the following keys:

* `max_batch_array_size` [Int]

Set limitation to json array size of batch request .
When a request whose json array size is over the limit comes, `request` method returns a invalid error json.

The default value is `nil` (no limit).

* `allow_single_request` [Bool]

This module can accept not only batch requests, but also single requests (no batch requests) . For example, ```{"id":1, "jsonrpc": "2.0", "params": {}, "method": "hoge"}``` is a single request.

If `allow_single_request` is set to be `false`, a single request results to a invalid error json.

The default value is `true`.
* `before_subrequest` [Function ```function(self, ctx)```]

Specify the callback function fired just before throw subrequests. `ctx` argument is a [Context](#context) Object.

For example, you can set nginx variable (`ngx.var`) for logging subrequests, and you can manipulate request parameters dynamically.

* `after_subrequest` [Function ```function(self, ctx)```]

Specify the callback function fired just after throw subrequests. `ctx` argument is a [Context](#context) Object.

For example, we can set nginx variable (`ngx.var`) for logging subrequest results, and we can manipulate subrequest responses dynamically.

### request

```
usage:
res, err = client:request({
path = "/api",
request = ###jsonrpc request json###,
})
```

Decode request json and separate it, and make subrequest parallely to specified `path`.
It returns response json(`res`) which is generated by all the subrequest 's response json. `err` is set error message when lua script occurs an error.

It can accept following parameters.

* `request` [String] (requried)

A request JSON.

* `path` [String or Function ```function(self, ctx, req)```] (required)

Subrequest path like `"/api"`.

The type can be Function which decides path for each subrequest dynamically.

`ctx` argument is a [Context](#context) Object.

`req` argument is a single request json included by batch request json array. like ```{"id":1, "jsonrpc": "2.0", "params": {"user_id": 1}, "method": "getUser"}```.

To give one example, we can use this function for separating api endpoints by JSON-RPC method, and we can throw original request path information to subrequest.

Following configuration exmaple is that there are two endpoints, and dispatch batch requests to endpoints by jsonrpc method. Besides, endpoints have own API version as path prefix.

```lua
location ~ ^/(\d+\.\d+)/getUser$ {
# jsonrpc endpoint 1
}

location ~ ^/(\d+\.\d+)/updateUser$ {
# jsonrpc endppoint 2
}

location ~ ^/(\d+\.\d+)/batch$ {
set $version $1;
lua_need_request_body on;
content_by_lua {
local res, err = client:batch_request({
path = function(self, ctx, req)
return "/" .. ngx.var.version .. "/" .. req.method
end,
request = ngx.var.request_body,
});
if err then
ngx.log(ngx.CRIT, err);
ngx.exit(500);
return;
end
};
}

```

* `method` (string) optional

Specify HTTP method using by subrequests.
The default value is `ngx.HTTP_POST`.

## Object
### Context

`before_subrequest`, `after_subrequest`, and `path` callback functions has Context object in arguments.
Context object includes information of requests and subrequest responses, so which value it has or not changes by the request proccess.

Context object is a lua table, and has following keys.

* `path` [String or Function]

Specified by `request` method as `path`.

* `method` [String]

Specified by `request` method as `method`.

* `raw_request` [String]

request json specified by `request` method as `request`.

* `request` [Table]

lua table generated by decoding `raw_request` json.

* `is_batch` [Bool]

The request json is single request or batch request.

* `subreq_reqs` [Table]

The array of subrequests parameters.
This is the arguments of `ngx.location.capture_multi`.

* `subreq_resps` [Table]

The array of subrequests responses.
This is the response of `ngx.location.capture_multi`.

## Author

* Yusuke Enomoto ([mosa_siru](https://twitter.com/mosa_siru))

## License

Copyright 2014- Yusuke Enomoto (mosa_siru)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.