* Preliminary module implementation for Luci HTTPD
authorSteven Barth <steven@midlink.org>
Tue, 17 Jun 2008 16:16:27 +0000 (16:16 +0000)
committerSteven Barth <steven@midlink.org>
Tue, 17 Jun 2008 16:16:27 +0000 (16:16 +0000)
libs/httpd/luasrc/httpd/handler/file.lua [new file with mode: 0644]
libs/httpd/luasrc/httpd/module.lua [new file with mode: 0644]

diff --git a/libs/httpd/luasrc/httpd/handler/file.lua b/libs/httpd/luasrc/httpd/handler/file.lua
new file mode 100644 (file)
index 0000000..eb5aafd
--- /dev/null
@@ -0,0 +1,22 @@
+module("luci.httpd.handler.file", package.seeall)
+require("luci.httpd.module")
+require("luci.fs")
+require("ltn12")
+
+Simple = luci.util.class(luci.httpd.module.Handler)
+Response = luci.httpd.module.Response
+
+function Simple.__init__(self, docroot)
+       luci.httpd.module.Handler.__init__(self)
+       self.docroot = docroot
+end
+
+function Simple.handle(self, request, sourcein, sinkerr)
+       local file = self.docroot .. request.env.REQUEST_URI:gsub("../", "")
+       local size = luci.fs.stat(file, "size")
+       if size then
+               return Response(200, {["Content-Length"] = size}), ltn12.source.file(io.open(file))
+       else
+               return Response(404)
+       end
+end
\ No newline at end of file
diff --git a/libs/httpd/luasrc/httpd/module.lua b/libs/httpd/luasrc/httpd/module.lua
new file mode 100644 (file)
index 0000000..bb22798
--- /dev/null
@@ -0,0 +1,154 @@
+--[[
+LuCI - Lua Configuration Interface
+
+Copyright 2008 Steven Barth <steven@midlink.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+]]--
+module("luci.httpd.module", package.seeall)
+require("luci.util")
+require("ltn12")
+
+
+
+-- Server handler implementation
+Handler = luci.util.class()
+
+-- Constructor
+function Handler.__init__(self)
+       self.filters = {}
+end
+
+
+-- Adds a filter to the filter chain
+function Handler.addfilter(self, filter)
+       table.insert(self.filters, filter)
+end
+
+
+-- Creates a failure reply
+function Handler.failure(self, message)
+       response = {
+               status = 500,
+               headers = {
+                       ["Content-Type"] = "text/plain"
+               }
+       }
+       
+       sourceout = ltn12.source.string(message)
+       
+       return response, sourceout 
+end
+
+
+-- Processes a request
+function Handler.process(self, request, sourcein, sinkout, sinkerr)
+       -- Process incoming filters
+       for i, f in ipairs(self.filters) do
+               local i = f:get("input")
+               
+               if i then
+                       sourcein = ltn12.source.chain(sourcein, i) 
+               end
+               
+               if f.request then
+                       f:request(request)
+               end
+       end
+       
+       -- Run the handler
+       local stat, response, sourceout = luci.util.copcall(
+               self.handle, self, request, sourcein, sinkerr
+       )
+       
+       -- Check for any errors
+       if not stat then
+               response, sourceout = self:failure(response)
+       end
+       
+       -- Check data
+       if not luci.util.instanceof(response, Response) then
+               response, sourceout = self:failure("Core error: Invalid module response!")
+       end
+       
+       -- Process outgoing filters
+       for i, f in ipairs(self.filters) do
+               local o = f:get("output")
+               
+               if o then
+                       sourceout = ltn12.source.chain(sourceout, o) 
+               end
+               
+               if f.response then
+                       f:response(response)
+               end
+       end
+       
+       
+       -- Print status and headers
+       sinkout("HTTP/1.1 " .. response.status .. " " .. statusmsg[response.status] .. "\n")
+       for k, v in pairs(response.headers) do
+               sinkout(k .. ": " .. v .. "\n")
+       end
+       
+       -- End of Headers
+       sinkout("\n")
+       
+       -- Pump content
+       if sourceout then
+               ltn12.pump.all(sourceout, sinkout)
+       end
+end
+
+
+
+-- Server Filter implementation
+Filter = luci.util.class()
+
+function Filter.get(self, name)
+       return self[name] and function(...) return self[name](self, ...) end
+end
+
+-- Filters the incoming body stream
+-- abstract function Filter.input(chunk)
+
+-- Filters the outgoing body stream
+-- abstract function Filter.output(chunk)
+
+-- Filters the request object
+-- abstract function Filter.request(request)
+
+-- Filters the response object
+-- abstract function Filter.response(response)
+
+
+
+-- Handler Response 
+Response = luci.util.class()
+
+function Response.__init__(self, status, headers)
+       self.status = tonumber(status) or 200
+       self.headers = (type(headers) == "table") and headers or {}
+end
+
+function Response.addheader(self, key, value)
+       self.headers[key] = value
+end
+
+function Response.setstatus(self, status)
+       self.status = status
+end
+
+
+-- Status codes
+statusmsg = {
+       [200] = "OK",
+       [404] = "Not Found",
+       [500] = "Internal Server Error",
+}
\ No newline at end of file