~lastrosade/getcraft

bb63c92bc47ade749197722c69b3c02aa0234f48 — jeremy.shields 5 years ago 0d10f5f
moar
4 files changed, 156 insertions(+), 9 deletions(-)

M .gitignore
M src/index.lua
A src/json.lua
A src/routes.json.template
M .gitignore => .gitignore +1 -1
@@ 1,4 1,4 @@
lit
luvi
luvit

src/routes.json
\ No newline at end of file

M src/index.lua => src/index.lua +111 -8
@@ 1,11 1,114 @@
local port = "1337"
local host = "127.0.0.1"
local routeFile = "src/routes.json"

local json = require('json')
local http = require('http')

function vardump(value, depth, key)
	local linePrefix = ""
	local spaces = ""
	
	if key ~= nil then
		linePrefix = "["..key.."] = "
	end
	
	if depth == nil then
		depth = 0
	else
		depth = depth + 1
		for i=1, depth do spaces = spaces .. "  " end
	end
	
	if type(value) == 'table' then
		mTable = getmetatable(value)
		if mTable == nil then
			print(spaces ..linePrefix.."(table) ")
		else
			print(spaces .."(metatable) ")
			value = mTable
		end		
		for tableKey, tableValue in pairs(value) do
			vardump(tableValue, depth, tableKey)
		end
	elseif type(value)	== 'function' or 
		type(value)	== 'thread' or 
		type(value)	== 'userdata' or
		value		== nil
	then
		print(spaces..tostring(value))
	else
		print(spaces..linePrefix.."("..type(value)..") "..tostring(value))
	end
end

function scandir(directory)
    local i, t, popen = 0, {}, io.popen
    local pfile = popen('find "'..directory..'" -maxdepth 1 -not -type d')
    for filename in pfile:lines() do
        i = i + 1
		t[i] = filename
    end
    pfile:close()
    return t
end

function readAll(file)
    local f = assert(io.open(file, "rb"))
    local content = f:read("*all")
    f:close()
    return content
end

routesText = readAll(routeFile)
routes = json.decode(routesText).routes

http.createServer(function (req, res)
	local body = "Hello world\n"
	res:setHeader("Content-Type", "text/plain")
	res:setHeader("Content-Length", #body)
	res:setHeader("Location", "nice")
	res:finish(body)
end):listen(1337, '127.0.0.1')

print('Server running at http://127.0.0.1:1337/')
	local routed = false

	for _,route in pairs(routes) do

		if (req.url == route.req) then
			routed = true

			if (route.type == "text") then
				res:setHeader("Content-Type", "text/plain")
				res:setHeader("Content-Length", #route.res)
				res:finish(route.res)

			elseif (route.type == "file") then
				local content = readAll(route.res)
				res:setHeader("Content-Type", "text/plain")
				res:setHeader("Content-Length", #content)
				res:finish(content)
			end

			break
		end
	end

	if (req.url == "/") then
		routed = true

		local files = scandir('src/')
		body = ""
		for i,f in pairs(files) do
			local fi = readAll(f)
			-- print(f .. " - " .. #fi)
			body = body .. fi .. "\n\n"
		end

		res:setHeader("Content-Type", "text/plain")
		res:setHeader("Content-Length", #body)
		res:finish(body)
	end

	if (routed == false) then
		res:writeHead(404, {})
		res:setHeader("Content-Length", 0)
		res:finish()
	end

end):listen(port, host)

print('Server running at http://'..host..':'..port..'/')

A src/json.lua => src/json.lua +25 -0
@@ 0,0 1,25 @@
--
-- json.lua
--
-- Copyright (c) 2018 rxi
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
-- this software and associated documentation files (the "Software"), to deal in
-- the Software without restriction, including without limitation the rights to
-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-- of the Software, and to permit persons to whom the Software is furnished to do
-- so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in all
-- copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
--

local json = { _version = "0.1.1" } local encode local escape_char_map = { [ "\\" ] = "\\\\", [ "\"" ] = "\\\"", [ "\b" ] = "\\b", [ "\f" ] = "\\f", [ "\n" ] = "\\n", [ "\r" ] = "\\r", [ "\t" ] = "\\t", } local escape_char_map_inv = { [ "\\/" ] = "/" } for k, v in pairs(escape_char_map) do escape_char_map_inv[v] = k end local function escape_char(c) return escape_char_map[c] or string.format("\\u%04x", c:byte()) end local function encode_nil(val) return "null" end local function encode_table(val, stack) local res = {} stack = stack or {} if stack[val] then error("circular reference") end stack[val] = true if val[1] ~= nil or next(val) == nil then local n = 0 for k in pairs(val) do if type(k) ~= "number" then error("invalid table: mixed or invalid key types") end n = n + 1 end if n ~= #val then error("invalid table: sparse array") end for i, v in ipairs(val) do table.insert(res, encode(v, stack)) end stack[val] = nil return "[" .. table.concat(res, ",") .. "]" else for k, v in pairs(val) do if type(k) ~= "string" then error("invalid table: mixed or invalid key types") end table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) end stack[val] = nil return "{" .. table.concat(res, ",") .. "}" end end local function encode_string(val) return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' end local function encode_number(val) if val ~= val or val <= -math.huge or val >= math.huge then error("unexpected number value '" .. tostring(val) .. "'") end return string.format("%.14g", val) end local type_func_map = { [ "nil"     ] = encode_nil, [ "table"   ] = encode_table, [ "string"  ] = encode_string, [ "number"  ] = encode_number, [ "boolean" ] = tostring, } encode = function(val, stack) local t = type(val) local f = type_func_map[t] if f then return f(val, stack) end error("unexpected type '" .. t .. "'") end function json.encode(val) return ( encode(val) ) end local parse local function create_set(...) local res = {} for i = 1, select("#", ...) do res[ select(i, ...) ] = true end return res end local space_chars   = create_set(" ", "\t", "\r", "\n") local delim_chars   = create_set(" ", "\t", "\r", "\n", "]", "}", ",") local escape_chars  = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") local literals      = create_set("true", "false", "null") local literal_map = { [ "true"  ] = true, [ "false" ] = false, [ "null"  ] = nil, } local function next_char(str, idx, set, negate) for i = idx, #str do if set[str:sub(i, i)] ~= negate then return i end end return #str + 1 end local function decode_error(str, idx, msg) local line_count = 1 local col_count = 1 for i = 1, idx - 1 do col_count = col_count + 1 if str:sub(i, i) == "\n" then line_count = line_count + 1 col_count = 1 end end error( string.format("%s at line %d col %d", msg, line_count, col_count) ) end local function codepoint_to_utf8(n) local f = math.floor if n <= 0x7f then return string.char(n) elseif n <= 0x7ff then return string.char(f(n / 64) + 192, n % 64 + 128) elseif n <= 0xffff then return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) elseif n <= 0x10ffff then return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,                 f(n % 4096 / 64) + 128, n % 64 + 128) end error( string.format("invalid unicode codepoint '%x'", n) ) end local function parse_unicode_escape(s) local n1 = tonumber( s:sub(3, 6),  16 ) local n2 = tonumber( s:sub(9, 12), 16 ) if n2 then return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) else return codepoint_to_utf8(n1) end end local function parse_string(str, i) local has_unicode_escape = false local has_surrogate_escape = false local has_escape = false local last for j = i + 1, #str do local x = str:byte(j) if x < 32 then decode_error(str, j, "control character in string") end if last == 92 then if x == 117 then local hex = str:sub(j + 1, j + 5) if not hex:find("%x%x%x%x") then     decode_error(str, j, "invalid unicode escape in string") end if hex:find("^[dD][89aAbB]") then     has_surrogate_escape = true else     has_unicode_escape = true end else local c = string.char(x) if not escape_chars[c] then     decode_error(str, j, "invalid escape char '" .. c .. "' in string") end has_escape = true end last = nil elseif x == 34 then local s = str:sub(i + 1, j - 1) if has_surrogate_escape then s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape) end if has_unicode_escape then s = s:gsub("\\u....", parse_unicode_escape) end if has_escape then s = s:gsub("\\.", escape_char_map_inv) end return s, j + 1 else last = x end end decode_error(str, i, "expected closing quote for string") end local function parse_number(str, i) local x = next_char(str, i, delim_chars) local s = str:sub(i, x - 1) local n = tonumber(s) if not n then decode_error(str, i, "invalid number '" .. s .. "'") end return n, x end local function parse_literal(str, i) local x = next_char(str, i, delim_chars) local word = str:sub(i, x - 1) if not literals[word] then decode_error(str, i, "invalid literal '" .. word .. "'") end return literal_map[word], x end local function parse_array(str, i) local res = {} local n = 1 i = i + 1 while 1 do local x i = next_char(str, i, space_chars, true) if str:sub(i, i) == "]" then i = i + 1 break end x, i = parse(str, i) res[n] = x n = n + 1 i = next_char(str, i, space_chars, true) local chr = str:sub(i, i) i = i + 1 if chr == "]" then break end if chr ~= "," then decode_error(str, i, "expected ']' or ','") end end return res, i end local function parse_object(str, i) local res = {} i = i + 1 while 1 do local key, val i = next_char(str, i, space_chars, true) if str:sub(i, i) == "}" then i = i + 1 break end if str:sub(i, i) ~= '"' then decode_error(str, i, "expected string for key") end key, i = parse(str, i) i = next_char(str, i, space_chars, true) if str:sub(i, i) ~= ":" then decode_error(str, i, "expected ':' after key") end i = next_char(str, i + 1, space_chars, true) val, i = parse(str, i) res[key] = val i = next_char(str, i, space_chars, true) local chr = str:sub(i, i) i = i + 1 if chr == "}" then break end if chr ~= "," then decode_error(str, i, "expected '}' or ','") end end return res, i end local char_func_map = { [ '"' ] = parse_string, [ "0" ] = parse_number, [ "1" ] = parse_number, [ "2" ] = parse_number, [ "3" ] = parse_number, [ "4" ] = parse_number, [ "5" ] = parse_number, [ "6" ] = parse_number, [ "7" ] = parse_number, [ "8" ] = parse_number, [ "9" ] = parse_number, [ "-" ] = parse_number, [ "t" ] = parse_literal, [ "f" ] = parse_literal, [ "n" ] = parse_literal, [ "[" ] = parse_array, [ "{" ] = parse_object, } parse = function(str, idx) local chr = str:sub(idx, idx) local f = char_func_map[chr] if f then return f(str, idx) end decode_error(str, idx, "unexpected character '" .. chr .. "'") end function json.decode(str) if type(str) ~= "string" then error("expected argument of type string, got " .. type(str)) end local res, idx = parse(str, next_char(str, 1, space_chars, true)) idx = next_char(str, idx, space_chars, true) if idx <= #str then decode_error(str, idx, "trailing garbage") end return res end return json
\ No newline at end of file

A src/routes.json.template => src/routes.json.template +19 -0
@@ 0,0 1,19 @@
{
    "routes": [
        {
            "req": "/index",
            "type": "file",
            "res": "src/index.lua"
        },
        {
            "req": "/text",
            "type": "text",
            "res": "text"
        },
        {
            "req": "/src",
            "type": "directory",
            "res": "src/"
        }
    ]
}
\ No newline at end of file