ikibooru/pegasus/handler.lua

152 lines
3.4 KiB
Lua
Raw Normal View History

2024-06-01 17:40:11 +03:00
local Request = require 'pegasus.request'
local Response = require 'pegasus.response'
local mimetypes = require 'mimetypes'
local lfs = require 'lfs'
local function ternary(condition, t, f)
if condition then return t else return f end
end
local Handler = {}
Handler.__index = Handler
function Handler:new(callback, location, plugins)
local handler = {}
handler.callback = callback
handler.location = location or ''
handler.plugins = plugins or {}
local result = setmetatable(handler, self)
result:pluginsAlterRequestResponseMetatable()
return result
end
function Handler:pluginsAlterRequestResponseMetatable()
for _, plugin in ipairs(self.plugins) do
if plugin.alterRequestResponseMetaTable then
local stop = plugin:alterRequestResponseMetaTable(Request, Response)
if stop then
return stop
end
end
end
end
function Handler:pluginsNewRequestResponse(request, response)
for _, plugin in ipairs(self.plugins) do
if plugin.newRequestResponse then
local stop = plugin:newRequestResponse(request, response)
if stop then
return stop
end
end
end
end
function Handler:pluginsBeforeProcess(request, response)
for _, plugin in ipairs(self.plugins) do
if plugin.beforeProcess then
local stop = plugin:beforeProcess(request, response)
if stop then
return stop
end
end
end
end
function Handler:pluginsAfterProcess(request, response)
for _, plugin in ipairs(self.plugins) do
if plugin.afterProcess then
local stop = plugin:afterProcess(request, response)
if stop then
return stop
end
end
end
end
function Handler:pluginsProcessFile(request, response, filename)
for _, plugin in ipairs(self.plugins) do
if plugin.processFile then
local stop = plugin:processFile(request, response, filename)
if stop then
return stop
end
end
end
end
function Handler:processBodyData(data, stayOpen, response)
local localData = data
for _, plugin in ipairs(self.plugins or {}) do
if plugin.processBodyData then
localData = plugin:processBodyData(
localData,
stayOpen,
response.request,
response
)
end
end
return localData
end
function Handler:processRequest(port, client, server)
local request = Request:new(port, client, server)
if not request:method() then
client:close()
return
end
local response = Response:new(client, self)
response.request = request
local stop = self:pluginsNewRequestResponse(request, response)
if stop then
return
end
if request:path() and self.location ~= '' then
local path = ternary(request:path() == '/' or request:path() == '', 'index.html', request:path())
local filename = '.' .. self.location .. path
if not lfs.attributes(filename) then
response:statusCode(404)
end
stop = self:pluginsProcessFile(request, response, filename)
if stop then
return
end
local file = io.open(filename, 'rb')
if file then
response:writeFile(file, mimetypes.guess(filename or '') or 'text/html')
else
response:statusCode(404)
end
end
if self.callback then
response:statusCode(200)
response.headers = {}
response:addHeader('Content-Type', 'text/html')
self.callback(request, response)
end
if response.status == 404 and not response._isClosed then
response:writeDefaultErrorMessage(404)
end
end
return Handler