Spore


Reference

Global Functions

new_from_spec( desc1, [desc2, ...][, { options }] )

Instanciate a ReST client from one or more descriptions defined by a filename or an URL.

The optional table options allows to overwrite some parameters of the description:

  • authentication,
  • base_url,
  • expected_status,
  • formats,
  • unattended_params
local client = require 'Spore'.new_from_spec 'github.json'

new_from_string( desc1, [desc2, ...][, { options }] )

Same as new_from_spec, but works with inline description.

local client = require 'Spore'.new_from_string [[
{
    "base_url" : "http://smolder.parrot.org",
    "name" : "smolder",
    "methods" : {
        "upload" : {
            "path" : "/app/projects/process_add_report/:project_id",
            "method" : "POST",
            "form-data" : {
                "architecture"  : ":architecture",
                "platform"      : ":platform",
                "tags"          : ":tags",
                "comments"      : ":comments",
                "username"      : ":username",
                "password"      : ":password",
                "project_id"    : ":project_id",
                "report_file"   : "@:report_file"
            },
            "required_params" : [
                "project_id",
                "report_file",
                "username",
                "password"
            ],
            "optional_params" : [
                "architecture",
                "platform",
                "tags",
                "comments"
            ],
            "expected_status" : [ 302 ]
        }
    }
}
]]

local r = client:upload{
    tags         = 'linux, i686-linux-gnu-thread-multi, lua, 5.1',
    comments     = 'experiment with lua-Spore',
    username     = 'parrot-autobot',
    password     = 'qa_rocks',
    project_id   = 7,
    report_file  = 'test_lua51.tar.gz',
}
print(r.body)

new_from_lua( desc [, { options }] )

Instanciate a ReST client from a Lua table.

The optional table options allows to overwrite some parameters of the description (see new_from_spec).

local client = require 'Spore'.new_from_lua{
    base_url = 'http://services.org/restapi/',
    methods = {
        get_info = {
            path = '/show',
            method = 'GET',
        },
        get_user_info = {
            path = '/show',
            method = 'GET',
            required_params = {
                'user',
            },
        },
    },
}

local r = client:get_user_info{ user = 'John' }

Instance Methods

These methods are inherited from Spore.Core (so, do not use these name in API description).

enable( middleware [, args] )

Enable a middleware with the optional table args.

enable_if( cond, middleware [, args] )

Enable a conditional middleware.

client:enable_if(function (req)
                     return req.env.spore.caller ~= 'get_attachment'
                 end,
                 'Format.JSON')

reset_middlewares()

Removes all middlewares.

http_request( env )

Never directly called.

Global Variables

These variables allow to do some configuration.

debug

The default value is nil.

require 'Spore'.debug = io.stdout

errors

The default value is io.stderr.

methname_modifier

The default value is nil.

This function allows to alter the name of the method during the instanciation.

require 'Spore'.methname_modifier = function (name)
    local lowerCamelCase = name:gsub('_(%w)', function (c) return c:upper() end)
    return lowerCamelCase
end

Examples

GitHub via http

local Spore = require 'Spore'

local github = Spore.new_from_spec 'https://raw.github.com/SPORE/api-description/master/services/github.json'
github:enable 'Format.JSON'
github:enable('Auth.Basic', {
    username = 'schacon/token',
    password = '6ef8395fecf207165f1a82178ae1b984',
})
local res = github:get_info{format = 'json', username = 'schacon'}
print(res.status)               --> 200
print(res.headers['x-runtime']) --> 126ms
print(res.body.user.name)       --> Scott Chacon

GitHub via https

The HTTPS protocol requires LuaSec.

local Spore = require 'Spore'

local github = Spore.new_from_spec('https://raw.github.com/SPORE/api-description/master/services/github.json', {
    base_url = "https://github.com/api/v2/",
})
github:enable 'Format.JSON'
local res = github:get_info{format = 'json', username = 'schacon'}
print(res.status)               --> 200
print(res.headers['x-runtime']) --> 126ms
print(res.body.user.name)       --> Scott Chacon

CouchDB

This example comes from the book CouchDB, The Definitif Guide.

local base = 'https://raw.github.com/SPORE/api-description/master/apps/couchdb/'
local couchdb = require 'Spore'.new_from_spec(
    base .. 'server.json',
    base .. 'database.json',
    base .. 'document.json',
    base .. 'design.json',
    { base_url = 'http://127.0.0.1:5984/' })
couchdb:enable_if(function (req) return req.env.spore.caller ~= 'get_attachment' end, 'Format.JSON')

local r = couchdb:get_root()
print(r.body.couchdb)
print(r.body.version)

local r = couchdb:create_db{ db = 'albums' }
assert(r.body.ok)
local r = couchdb:create_db{ db = 'albums' }
print("error", r.body.error)
print("reason", r.body.reason)

local r = couchdb:add_document{
    db = 'albums',
    id = '6e1295ed6c29495e54cc05947f18c8af',
    payload = {
        title = "There is Nothing Left to Lose",
        artist = "Foo Fighters",
    },
}
assert(r.body.ok)
print("id", r.body.id)
print("rev", r.body.rev)

local r = couchdb:get_uuids()
assert(#r.body.uuids == 1)
for i, v in ipairs(r.body.uuids) do print("uuid",i, v) end

local r = couchdb:get_document{
    db = 'albums',
    id = '6e1295ed6c29495e54cc05947f18c8af',
}
print("_id", r.body._id)
print("_rev", r.body._rev)
print("title", r.body.title)
print("artist", r.body.artist)
local rev1 = r.body._rev

local r = couchdb:add_document{
    db = 'albums',
    id = '6e1295ed6c29495e54cc05947f18c8af',
    payload = {
        title = "There is Nothing Left to Lose",
        artist = "Foo Fighters",
        year = 1997,
    },
}
print("error", r.body.error)
print("reason", r.body.reason)

local r = couchdb:add_document{
    db = 'albums',
    id = '6e1295ed6c29495e54cc05947f18c8af',
    payload = {
        _rev = rev1,
        title = "There is Nothing Left to Lose",
        artist = "Foo Fighters",
        year = 1997,
    },
}
assert(r.body.ok)
print("id", r.body.id)
print("rev", r.body.rev)
local rev2 = r.body.rev

local r = couchdb:add_document{
    db = 'albums',
    id = '70b50bfa0a4b3aed1f8aff9e92dc16a0',
    payload = {
        title = "Blackened Sky",
        artist = "Biffy Clyro",
        year = 2002,
    },
}
print("Location", r.headers['location'])
assert(r.body.ok)
print("id", r.body.id)
print("rev", r.body.rev)

local slurp = require 'Spore.Protocols'.slurp
local r = couchdb:add_attachment{
    db = 'albums',
    id = '6e1295ed6c29495e54cc05947f18c8af',
    rev = rev2,
    file = 'api.png',
    content_type = 'image/png',
    payload = slurp'api.png',
}
assert(r.body.ok)
print("id", r.body.id)
print("rev", r.body.rev)

local r = couchdb:get_attachment{
    db = 'albums',
    id = '6e1295ed6c29495e54cc05947f18c8af',
    file = 'api.png',
}
print("Content-Type", r.headers['content-type'])
print("Content-Length", r.headers['content-length'])

local r = couchdb:get_document{
    db = 'albums',
    id = '6e1295ed6c29495e54cc05947f18c8af',
}
print("_id", r.body._id)
print("_rev", r.body._rev)
print("title", r.body.title)
print("artist", r.body.artist)
for k, v in pairs(r.body._attachments) do
    print(k)
    for kk, vv in pairs(v) do print(kk, vv) end
end

with Google & OAuth 1.0

This example uses the service Google URL Shortener.

local url = require 'socket.url'
local Spore = require 'Spore'
--Spore.debug = io.stdout

local function get_google_keys (scope, keys)
    local oauth = require 'Spore'.new_from_spec 'https://raw.github.com/SPORE/api-description/master/services/googleoauth.json'
    oauth:enable('Auth.OAuth', keys)
    local r1 = oauth:get_request_token{
        scope = scope,
    }
    print("request", r1.body)
    for k, v in r1.body:gmatch'([^&=]+)=([^&=]*)&?' do keys[k] = url.unescape(v) end

    local r2 = oauth:authorize_token{ oauth_token = keys.oauth_token }
    print("authorize", r2.status, r2.headers.location)

    os.execute("x-www-browser " .. r2.headers.location)

    print "enter oauth_verifier:"
    local input = io.stdin:read('*l')
    print("oauth_verifier=]" .. input .. "[")
    keys.oauth_verifier = input

    local r3 = oauth:get_access_token()
    print("access", r3.body)
    for k, v in r3.body:gmatch'([^&=]+)=([^&=]*)&?' do keys[k] = url.unescape(v) end

    keys.oauth_callback_confirmed = nil
    keys.oauth_verifier = nil
    return keys
end


local client = require 'Spore'.new_from_spec 'https://raw.github.com/SPORE/api-description/master/services/googleshortener.json'
client:enable 'Format.JSON'
client:enable('Auth.OAuth', get_google_keys('https://www.googleapis.com/auth/urlshortener', {
    oauth_consumer_key    = '000000000000.apps.googleusercontent.com',
    oauth_consumer_secret = 'XXXXXXXXXXXXXXXXXXXXXXXX',
}))

local r = client:insert{ payload = { longUrl = 'http://www.google.com/' } }
print(r.body.id, r.body.longUrl)

local r = client:list()
print "\nAUTHORIZED\n"
for k, v in pairs(r.body) do
    print(k, v)
end