-------------------------------------------------------------------------------- -- Title: Web.lua -- Description: Like a square peg in a round hole -- Author: Raphaël Szwarc http://alt.textdrive.com/lua/ -- Creation Date: February 1, 2005 -- Legal: Copyright (C) 2005 Raphaël Szwarc -------------------------------------------------------------------------------- -- import dependencies local LWApplication = require( "LWApplication" ) local LWService = require( "LWService" ) local LULog = require( "LULog" ) local LUMap = require( "LUMap" ) local LUTask = require( "LUTask" ) -- define the class local super = LWService local self = super() function self:init( aPrefix, someMappings ) self = super.init( self, aPrefix ) self._mappings = someMappings return self end function self:buffers() if self._buffers == nil then self._buffers = LUMap( nil, "k" ) end return self._buffers end function self:buffer() local aTask = LUTask:currentTask() local someBuffers = self:buffers() local aBuffer = someBuffers:get( aTask ) if aBuffer == nil then aBuffer = {} someBuffers:put( aTask, aBuffer ) end return aBuffer end function self:contexts() if self._contexts == nil then self._contexts = LUMap( nil, "kv" ) end return self._contexts end function self:context() return self:contexts():get( LUTask:currentTask() ) end function self:mappings() return self._mappings or {} end function self:request() return self:context():request() end function self:response() return self:context():response() end function self:write( ... ) local aBuffer = self:buffer() local aCount = select( "#", ... ) for anIndex = 1, aCount do local aValue = select( anIndex, ... ) aBuffer[ #aBuffer + 1 ] = tostring( aValue ) end end function self:flushBuffer() local aTask = LUTask:currentTask() local someBuffers = self:buffers() local aBuffer = someBuffers:get( aTask ) if aBuffer ~= nil and #aBuffer > 0 then self:response():writeContent( table.concat( aBuffer, "" ) ) someBuffers:remove( aTask ) end end function self:iterator() local aPrefix = self:prefix() local someMappings = self:mappings() local aPairIterator = ipairs( someMappings ) local anIndex = 0 local anIterator = function() local aPattern = nil local anHandler = nil anIndex, aPattern = aPairIterator( someMappings, anIndex ) if anIndex ~= nil then anIndex, anHandler = aPairIterator( someMappings, anIndex ) if aPattern ~= nil and anHandler ~= nil then aPattern = "^" .. aPrefix .. aPattern .. "$" return aPattern, anHandler end end return nil end return anIterator end local function Print( ... ) self:write( ... ) end function self:handlerWithMethod( anHandler, aMethod, someMatches ) local aType = type( anHandler ) if aType == "string" then anHandler = require( anHandler ) aType = type( anHandler ) end if aType == "table" then table.insert( someMatches, 1, anHandler() ) anHandler = anHandler[ aMethod:lower() ] end if type( anHandler ) == "function" then local anEnviromnent = { print = Print } setmetatable( anEnviromnent, { __index = _G } ) setfenv( anHandler, anEnviromnent ) else anHandler = nil end return anHandler, someMatches end -- method to run this service function self:run( aContext ) local aMethod = aContext:request():method() local anURI = aContext:request():uri() if aMethod ~= nil and anURI ~= nil and anURI:path() ~= nil then local aPath = anURI:path() for aPattern, anHandler in self:iterator() do if aPath:find( aPattern ) ~= nil then local someMatches = { aPath:match( aPattern ) } anHandler, someMatches = self:handlerWithMethod( anHandler, aMethod, someMatches ) if anHandler ~= nil then self:contexts():put( LUTask:currentTask(), aContext ) anHandler( unpack( someMatches ) ) self:flushBuffer() return self end end end end return super.run( self, aContext ) end -- method to start this service function self:start( someMappings, aPort ) local anApplication = LWApplication( aPort or 1080 ) local aService = self:new( "/", someMappings ) anApplication:registerService( aService ) LULog:info( anApplication ) anApplication:start() end return self