diff --git a/example/app.lua b/example/app.lua index 2856077..de46a35 100644 --- a/example/app.lua +++ b/example/app.lua @@ -11,8 +11,73 @@ local Pegasus = require 'pegasus' local Compress = require 'pegasus.plugins.compress' local Downloads = require 'pegasus.plugins.downloads' local Files = require 'pegasus.plugins.files' +local Router = require 'pegasus.plugins.router' +local json = require 'pegasus.json' -- local TLS = require 'pegasus.plugins.tls' + +-- example data for the "router" plugin +local routes do + local testData = { + Jane = { firstName = "Jane", lastName = "Doe", age = 25 }, + John = { firstName = "John", lastName = "Doe", age = 30 }, + } + + routes = { + -- router-level preFunction runs before the method prefunction and callback + preFunction = function(req, resp) + local stop = false + local headers = req:headers() + local accept = (headers.accept or "*/*"):lower() + if not accept:find("application/json", 1, true) and + not accept:find("application/*", 1, true) and + not accept:find("*/*", 1, true) then + + resp:writeDefaultErrorMessage(406, "This API only produces 'application/json'") + stop = true + end + return stop + end, + + ["/people"] = { + GET = function(req, resp) + resp:statusCode(200) + resp:addHeader("Content-Type", "application/json") + resp:write(json.encode(testData)) + end, + }, + + ["/people/{name}"] = { + -- path-level preFunction runs before the actual method callback + preFunction = function(req, resp) + local stop = false + local name = req.pathParameters.name + if not testData[name] then + local err = ("'%s' is an unknown person"):format(name) + resp:writeDefaultErrorMessage(404, err) + stop = true + end + return stop + end, + + -- callback per method + GET = function(req, resp) + resp:statusCode(200) + resp:addHeader("Content-Type", "application/json") + resp:write(json.encode(testData[req.pathParameters.name])) + end, + + -- postFunction runs after the actual method callback + postFunction = function(req, resp) + local stop = false + print("served " .. req.pathParameters.name .. "'s data") + return stop + end, + } + } +end + + local server = Pegasus:new({ port = '9090', plugins = { @@ -39,6 +104,11 @@ local server = Pegasus:new({ location = '/example/root/', }, + Router:new { + prefix = "/api/1v0/", + routes = routes, + }, + Compress:new(), } }) diff --git a/example/copas.lua b/example/copas.lua index 586e128..e50537e 100644 --- a/example/copas.lua +++ b/example/copas.lua @@ -12,6 +12,11 @@ local Handler = require 'pegasus.handler' local copas = require('copas') local socket = require('socket') local Downloads = require 'pegasus.plugins.downloads' +local Files = require 'pegasus.plugins.files' +local Router = require 'pegasus.plugins.router' +local Compress = require 'pegasus.plugins.compress' +local json = require 'pegasus.json' + --- Creates a new server within the Copas scheduler. -- @tparam table opts options table. @@ -25,7 +30,6 @@ local Downloads = require 'pegasus.plugins.downloads' -- @return the server-socket on success, or nil+err on failure local function newPegasusServer(opts) opts = opts or {} - assert(opts.location or opts.callback, "either 'location' or 'callback' must be provided") assert(opts.port, "option 'port' must be provided") local server_sock, err = socket.bind(opts.interface or '*', opts.port) @@ -36,6 +40,10 @@ local function newPegasusServer(opts) local server_ip, server_port = server_sock:getsockname() if not server_ip then return nil, "failed to get server socket name; "..tostring(server_port) + else + if server_ip == "0.0.0.0" then + server_ip = "localhost" + end end local hdlr = Handler:new(opts.callback, opts.location, opts.plugins) @@ -49,6 +57,68 @@ local function newPegasusServer(opts) end +-- example data for the "router" plugin +local routes do + local testData = { + Jane = { firstName = "Jane", lastName = "Doe", age = 25 }, + John = { firstName = "John", lastName = "Doe", age = 30 }, + } + + routes = { + -- router-level preFunction runs before the method prefunction and callback + preFunction = function(req, resp) + local stop = false + local headers = req:headers() + local accept = (headers.accept or "*/*"):lower() + if not accept:find("application/json", 1, true) and + not accept:find("application/*", 1, true) and + not accept:find("*/*", 1, true) then + + resp:writeDefaultErrorMessage(406, "This API only produces 'application/json'") + stop = true + end + return stop + end, + + ["/people"] = { + GET = function(req, resp) + resp:statusCode(200) + resp:addHeader("Content-Type", "application/json") + resp:write(json.encode(testData)) + end, + }, + + ["/people/{name}"] = { + -- path-level preFunction runs before the actual method callback + preFunction = function(req, resp) + local stop = false + local name = req.pathParameters.name + if not testData[name] then + local err = ("'%s' is an unknown person"):format(name) + resp:writeDefaultErrorMessage(404, err) + stop = true + end + return stop + end, + + -- callback per method + GET = function(req, resp) + resp:statusCode(200) + resp:addHeader("Content-Type", "application/json") + resp:write(json.encode(testData[req.pathParameters.name])) + end, + + -- postFunction runs after the actual method callback + postFunction = function(req, resp) + local stop = false + print("served " .. req.pathParameters.name .. "'s data") + return stop + end, + } + } +end + + -- Create http server assert(newPegasusServer{ @@ -80,14 +150,25 @@ assert(newPegasusServer{ }, sni = nil, }, - location = '/example/root/', - callback = nil, + plugins = { Downloads:new { - prefix = "downloads", + location = '/example/root/', + prefix = 'downloads', stripPrefix = true, }, - }, + + Files:new { + location = '/example/root/', + }, + + Router:new { + prefix = "/api/1v0/", + routes = routes, + }, + + Compress:new(), + } }) -- Start diff --git a/example/root/index.html b/example/root/index.html index f890903..6016277 100644 --- a/example/root/index.html +++ b/example/root/index.html @@ -17,5 +17,15 @@ Age: +
Try the following API calls for the Router plugin: +
/api/1v0/people
/api/1v0/people/John
/api/1v0/people/Mary
(fails with 404, change to "Jane" to make it work)curl -v -X POST http://localhost:9090/api/1v0/people/John
(a POST request, failing with 405)curl -v -X GET -H "Accept: application/xml" http://localhost:9090/api/1v0/people/John
(failing with 406)