summaryrefslogblamecommitdiffstats
path: root/lem/hathaway.lua
blob: b23934cb3f063ab25a07bfbc3950386a134f3fca (plain) (tree)
1
2
3
4


                                                 
                                               














                                                                    
                                        


            



















                                                                

                                                






                         




                                               
                    
                                 


                                                   
                                            




                                                    



                                                               
                                    
                                                                             




















































                                                                                           










                                                            
                                        




                                                                               

                                                 
                            
                                                              
                           


                                   
                                         



                                                             
                                   
                                                                                
                   


                                          

                                                                           
 
                                        
 






















                                 
--
-- This file is part of LEM, a Lua Event Machine.
-- Copyright 2011-2012 Emil Renner Berthing
-- Copyright 2012      Asbjørn Sloth Tønnesen
--
-- LEM is free software: you can redistribute it and/or
-- modify it under the terms of the GNU General Public License as
-- published by the Free Software Foundation, either version 3 of
-- the License, or (at your option) any later version.
--
-- LEM is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with LEM.  If not, see <http://www.gnu.org/licenses/>.
--

local server = require 'lem.http.server'

local M = {}

function M.not_found(req, res)
	if req.headers['Expect'] ~= '100-continue' then
		req:body()
	end

	res.status = 404
	res.headers['Content-Type'] = 'text/html; charset=UTF-8'
	res:add([[
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Not Found</title>
</head>
<body>
<h1>Not found</h1>
</body>
</html>
]])
end

M.status_string = server.status_string
M.method_not_allowed = server.method_not_allowed

function M.debug() end

do
	local lookup = {}
	M.lookup = lookup

	function M.GET(path, handler)
		local entry = lookup[path]
		if entry then
			entry['HEAD'] = handler
			entry['GET'] = handler
		else
			entry = {
				['HEAD'] = handler,
				['GET'] = handler,
			}
			lookup[path] = entry
		end
	end

	do
		local function static_setter(method)
			return function(path, handler)
				local entry = lookup[path]
				if entry then
					entry[method] = handler
				else
					lookup[path] = { [method] = handler }
				end
			end
		end

		M.POST   = static_setter('POST')
		M.PUT    = static_setter('PUT')
		M.DELETE = static_setter('DELETE')
	end

	function M.GETM(pattern, handler)
		local i = 1
		while true do
			local entry = lookup[i]
			if entry == nil then
				lookup[i] = { pattern,
					['GET'] = handler,
					['HEAD'] = handler
				}
				break
			end
			if entry[1] == pattern then
				entry['GET'] = handler
				entry['HEAD'] = handler
				break
			end
			i = i + 1
		end
	end

	do
		local function match_setter(method)
			return function(pattern, handler)
				local i = 1
				while true do
					local entry = lookup[i]
					if entry == nil then
						lookup[i] = { pattern, [method] = handler }
						break
					end
					if entry[1] == pattern then
						entry[method] = handler
						break
					end
					i = i + 1
				end
			end
		end

		M.POSTM   = match_setter('POST')
		M.PUTM    = match_setter('PUT')
		M.DELETEM = match_setter('DELETE')
	end

	local function check_match(entry, req, res, ok, ...)
		if not ok then return false end
		local handler = entry[req.method]
		if handler then
			handler(req, res, ok, ...)
		else
			M.method_not_allowed(req, res)
		end
		return true
	end

	local function handler(req, res)
		local method, path, version = req.method, req.path, req.version

		local entry = lookup[path]
		if entry then
			local handler = entry[method]
			if handler then
				handler(req, res)
			else
				M.method_not_allowed(req, res)
			end
		else
			local i = 0
			repeat
				i = i + 1
				local entry = lookup[i]
				if not entry then
					M.not_found(req, res)
					break
				end
			until check_match(entry, req, res, path:match(entry[1]))
		end
	end

	function M.Hathaway(address, port)
		local ret, err = server.tcp4_listen(address, port, handler)
		if not ret then M.debug(err) return nil, err end

		M.server = server.server

		return true
	end
end

function M.import(env)
	if not env then
		env = _G
	end

	env.GET      = M.GET
	env.POST     = M.POST
	env.PUT      = M.PUT
	env.DELETE   = M.DELETE
	env.GETM     = M.GETM
	env.POSTM    = M.POSTM
	env.PUTM     = M.PUTM
	env.DELETEM  = M.DELETEM
	env.Hathaway = M.Hathaway
end

return M

-- vim: ts=2 sw=2 noet: