REST Lua Service

Introduction

The RestLuaService is a service for initiating Lua scripts running within the LogicApp.

The RestLuaService receives messages from one or more instances of the RestServerApp which is configured to receive REST/HTTP(S) Requests from an external client.

The RestLuaService communicates with the RestServerApp using the REST-S-… messages.

Configuring RestLuaService

The RestLuaService is configured within a LogicApp.

    <?xml version="1.0" encoding="utf-8"?>
    <n2svcd>
      ...
      <applications>
        ...
        <application name="Logic" module="LogicApp">
          <include>
            <lib>../apps/logic/lib</lib>
          </include>
          <parameters>
            ...
          </parameters>
          <config>
            <services>
              <service module="RestServerApp::RestLuaService" libs="../apps/rest_s/lib" script_dir="/var/lib/n2svcd/logic/rest"/>
            </services>
            <agents>
              ...
            </agents>
          </config>
        </application>
        ...
      </application>
      ...
    </n2svcd>

In addition to the Common LogicApp Service Configuration, note the following specific attribute notes, and service-specific attributes.

Under normal installation, the following service attributes apply:

Parameter Name Type XML Type Description
module String Attribute [Required] The module name containing the Lua Service code: RestServerApp::RestLuaService
libs String Element Location of the module for RestLuaService.
(Default: ../apps/rest_s/lib)
script_dir String Attribute [Required] The directory containing scripts used by this service.

Script Selection (REST Request)

Script selection is not configured. The script name is simply the part after the “/” of the path.

e.g. an inbound request with path /APP/rest/echo will map to a script name of echo, which will be satisfied by a file named echo.lua in any of the directories configured as lua_script_dir in the LogicApp.

Refer to the LogicApp configuration for more information on directories, library paths, and script caching parameters.

Script Global Variables

Scripts run with this service have access to the Common LUA Service Global Variables.

There are no service-specific global variables.

Script Entry Parameters (REST Request)

The Lua script must be a Lua chunk which returns an n2svcd.handler, such as the following example, which includes a single user-level HTTP header named Echo-Flag:

    local n2svcd = require "n2.n2svcd"

    local handler = function (rest)
        n2svcd.debug ("Echo Supplied REST Inputs:")
        n2svcd.debug_var (rest)

        return { 
            content_type = rest.content_type, 
            content = rest.content,
            http_headers = { { name = 'Echo-Flag', value = 'true' } }
        }
    end

    return n2svcd.handler (handler)

The handler will be executed with a single rest entry parameter which is an object with the following attributes:

Attribute Type Description
.remote_host String The remote IP address from which the REST HTTP(S) request was sent.
.remote_port Integer The remote IP port from which the REST HTTP(S) request was sent.
.method String The HTTP Request method.
.uri String The URI for which the request was received.
Includes only path and query. No host/port/auth/user/fragment is present.
.path String The URI path.
.query String The URI query string (the part following "?" in the URI).
.query_args String or Object If the .query attribute contains & or = then this query_args contains a table of the name and values, decoded according to common web form conventions. If you wish to have full control of the decoding, then you should directly reference the undecoded .query.
.content_type String The HTTP Request Content-Type header value.
.content String The HTTP Request content.
.http_headers Array of Object The list of HTTP headers parsed from the HTTP Request (see below for object structure).
All HTTP headers are present, including Content-Length and Content-Type.
If a HTTP header was repeated in the HTTP Request, then it is repeated in this Array.

Each object in the .http_headers Array for the rest entry parameter has the following structure.

Field Type Description
.name String [Required] The name of the HTTP Request header.
.value String [Required] The full string value of the HTTP Request header.

Script Return Parameters (REST Response)

The Lua script is responsible for determing the REST Response which will be sent back in reply to the original REST Request.

The simplest way to do this is by the return value given back to the service at the end of script execution.

For full control over the REST response, the script return value may be a response object with the following attributes:

Field Type Description
response Object Container for the REST response parameters we are to send.
.code Integer [Required] The HTTP Response Status Code to send (e.g. 200)
.content_type String The HTTP Response Content-Type header value to send.
(Default = Do not return Content-Type header)
.content String The HTTP Request content to send.
(Default = None)
.http_headers Array of Objects Additional user-level header objects to apply to an outbound HTTP Response (see below for object structure).
These headers are added after any headers defined by static RestServerApp application configuration.
You should not set the Content-Type or Content-Length headers.
(Default = No Additional Headers)

Each object in the .http_headers Array for the response object has the following structure.

Field Type Description
.name String [Required] The name of the HTTP Response header.
.value String [Required] The full string value of the HTTP Response header.
.replace 0 / 1 If 1 then all previous headers of this name are removed, and this header replaces them.
(Default = Append to the existing headers, do not replace)

Alternatively, the script may return a simple string, or nil.

Example (returning a Table REST Response):

    local n2svcd = require "n2.n2svcd"

    local handler = function (rest)
        return ({ content_type = "application/json", content = '{ "numrows": 1 }'})
    end

    return n2svcd.handler (handler)

Alternatively, a script may return a simple string instead of a Table.

Example (returning a String REST Response):

    local n2svcd = require "n2.n2svcd"

    local handler = function (rest)
        return "I AM OK YOU ARE OK"
    end

    return n2svcd.handler (handler)

This is a shorthand for code = 200, content_type = text/plain.

Alternatively, a script may return nil.

Example (returning a 200 OK with no Content):

    local n2svcd = require "n2.n2svcd"

    local handler = function (rest)
        return nil
    end

    return n2svcd.handler (handler)

This is a shorthand for code = 200, no Content, no Content-Type.

The RestLuaService API

The REST Server API can be loaded as follows.

    local rest_server_api = require "n2.n2svcd.rest_server"

It is not necessary to load the REST Server API if you are only using the simple response mechanism described above. It is only required if you wish to use any of the extended features described below.

.response

When a Lua Script needs to perform extended processing, it may wish to send an early REST response before the script completes. This can be done with the response method on the REST API.

The response method takes a single response parameter. The structure of this response parameter is identical to the response parameter which may be returned as the script return parameter, as described above in Script Return Parameters (REST Response)

The response method returns true.

[Fragment] Example (403 Early Response with text/plain content and cookie):

    ...
    local headers = {}
    utils.http_headers_set_cookie (headers, "SESSION$", "<none>")

    rest_server_api.response ({ 
        code = 403, 
        content = "ACCESS DENIED!", 
        content_type = "text/plain", 
        http_headers = headers
    })
    ...
    [post-processing after REST transaction is concluded]
    ...

[Fragment] Example (200 Early Response with text/plain content):

    ...
    rest_server_api.response ("THANKS FOR CALLING")
    ...
    [post-processing after REST transaction is concluded]