Home

Awesome

lua-resty-jsonrpc-batch

The Lua-Openresty implementation of JSON-RPC 2.0 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

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

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:

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.

    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
        };
    }

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.

Specified by request method as path.

Specified by request method as method.

Author

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.