Added experimental lua http server

This commit is contained in:
Martin Schröder 2015-08-25 18:26:44 +02:00
parent b8f45b06ba
commit cb024c1cb8
3 changed files with 121 additions and 8 deletions

103
http-server.lua Normal file
View File

@ -0,0 +1,103 @@
local http = require("http")
local fs = require('fs')
local uv = require("uv");
local json = require("json");
require("ubus");
local PORT = 8000
local conn = ubus.connect()
if not conn then
error("Failed to connect to ubus")
end
local mime_types = {
html = "text/html",
js = "application/javascript",
css = "text/css",
jpg = "image/jpeg",
jpeg = "image/jpeg",
png = "image/png",
text = "text/plain"
};
local rpcid = 0;
http.createServer({}, function(req, res)
--print(json.stringify(req));
local path = req.url;
if path == "/" then path = "index.html"; end
path = "/www/"..path;
local ext = path:match("^.+(%..+)$") or "text";
local not_found = "Not found!";
if(req.method == "POST" and req.url == "/ubus") then
local buffer = {}
req:on('data', function(chunk)
table.insert(buffer, chunk)
end)
req:on('end', function()
local data = "";
for i,v in ipairs(buffer) do data = data..v; end
local post = json.parse(data);
local result = { jsonrpc = "2.0", id = rpcid };
rpcid = rpcid +1;
if post.method == "list" then
local objects = {};
local namespaces = conn:objects()
for i, n in ipairs(namespaces) do
local signatures = conn:signatures(n)
local methods = {};
print("object="..n);
for p, s in pairs(signatures) do
local meth = {};
print("\tprocedure=" .. p)
for k, v in pairs(s) do
print("\t\tattribute=" .. k .. " type=" .. v)
end
methods[p] = meth;
end
objects[n] = methods;
end
result["result"] = objects;
elseif post.method == "call" then
print("Call: "..post.params[2].." "..post.params[3].." "..json.stringify(post.params[4]));
local r,code = conn:call(post.params[2], post.params[3], post.params[4]);
result["result"] = {code or 0, r or {}};
end
local body = json.stringify(result);
res:setHeader("Content-Type", "text/json");
res:setHeader("Content-Length", #body)
print("Result: "..body);
res:finish(body);
end)
else
if fs.existsSync(path..".gz") then
print("Found gzipped version of "..path);
path = path..".gz";
res:setHeader("Content-Encoding", "gzip");
end
if not fs.existsSync(path) then
res:setHeader("Content-Type", "text/plain")
res:setHeader("Content-Length", #not_found)
res:finish(not_found)
else
local body = fs.readFileSync(path);
res:setHeader("Content-Type", mime_types[ext])
res:setHeader("Content-Length", #body)
res:finish(body)
end
end
end):listen(PORT)
print("Server listening at http://localhost:"..PORT)
uv.run();

View File

@ -149,12 +149,14 @@ function ServerResponse:flushHeaders()
self.headersSent = true
local headers = self.headers
local statusCode = self.statusCode
local head = {}
local sent_date, sent_connection, sent_transfer_encoding, sent_content_length
for key,value in pairs(headers) do
for i,v in ipairs(headers) do
local key, value = unpack(v);
local klower = tostring(key):lower()
head[#head + 1] = {tostring(key), tostring(value)}
table.insert(head, {tostring(key), tostring(value)});
if klower == "connection" then
self.keepAlive = value:lower() ~= "close"
sent_connection = true
@ -243,7 +245,7 @@ function ServerResponse:writeHead(newStatusCode, newHeaders)
assert(not self.headersSent, "headers already sent")
self.statusCode = newStatusCode
local headers = setmetatable({}, headerMeta)
self.headers = headers
--self.headers = headers
for k, v in pairs(newHeaders) do
headers[k] = v
end

View File

@ -274,7 +274,10 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
local valtojson = valmeta and valmeta.__tojson
if valtojson then
if tables[value] then
return exception('reference cycle', value, state, buffer, buflen)
buflen = buflen + 1
buffer[buflen] = quotestring ("[[cyclic value]]");
return buflen;
--return exception('reference cycle', value, state, buffer, buflen)
end
tables[value] = true
state.bufferlen = buflen
@ -365,8 +368,10 @@ encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, s
end
tables[value] = nil
else
return exception ('unsupported type', value, state, buffer, buflen,
"type '" .. valtype .. "' is not supported by JSON.")
buflen = buflen + 1
buffer[buflen] = quotestring ("["..valtype.."]");
--return exception ('unsupported type', value, state, buffer, buflen,
-- "type '" .. valtype .. "' is not supported by JSON.")
end
return buflen
end
@ -380,7 +385,10 @@ function json.encode (value, state)
local ret, msg = encode2 (value, state.indent, state.level or 0,
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
if not ret then
error (msg, 2)
state.bufferlen = nil
state.buffer = nil
return concat (buffer)
--error (msg, 2)
elseif oldbuffer == buffer then
state.bufferlen = ret
return true