Mercurial Hosting > luan
changeset 1171:794ddcfbee20
remove http/impl
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 11 Feb 2018 02:41:23 -0700 |
parents | 3a0f58d09ee7 |
children | 1aa6dd74f3fc |
files | src/luan/modules/http/Http.luan src/luan/modules/http/HttpServicer.java src/luan/modules/http/LuanHandler.java src/luan/modules/http/NotFound.java src/luan/modules/http/Server.luan src/luan/modules/http/impl/Http.luan src/luan/modules/http/impl/HttpServicer.java src/luan/modules/http/impl/LuanHandler.java src/luan/modules/http/impl/NotFound.java src/luan/modules/http/impl/Server.luan |
diffstat | 10 files changed, 476 insertions(+), 478 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/modules/http/Http.luan Sun Feb 11 02:34:35 2018 -0700 +++ b/src/luan/modules/http/Http.luan Sun Feb 11 02:41:23 2018 -0700 @@ -1,1 +1,160 @@ -return require "luan:http/impl/Http.luan" +java() +local Luan = require "luan:Luan.luan" +local error = Luan.error +local ipairs = Luan.ipairs or error() +local pairs = Luan.pairs or error() +local type = Luan.type or error() +local Io = require "luan:Io.luan" +local Html = require "luan:Html.luan" +local url_encode = Html.url_encode or error() +local Table = require "luan:Table.luan" +local clear = Table.clear or error() +local Package = require "luan:Package.luan" +local String = require "luan:String.luan" +local lower = String.lower or error() +local matches = String.matches or error() +local HttpServicer = require "java:luan.modules.http.HttpServicer" +local IoLuan = require "java:luan.modules.IoLuan" +local JavaLuan = require "java:luan.Luan" +local Response = require "java:luan.webserver.Response" +local ResponseOutputStream = require "java:luan.webserver.ResponseOutputStream" +local Status = require "java:luan.webserver.Status" +local OutputStreamWriter = require "java:java.io.OutputStreamWriter" +local HashMap = require "java:java.util.HashMap" + + +local Http = {} + +Http.version = "luan" + +function Http.new_request(java) + local this = {} + Http.request = this + if java == nil then + this.method = "GET" + this.headers = {} + this.parameters = {} + this.cookies = {} + else + this.java = java + this.method = java.method or error() + this.raw_path = java.rawPath or error() + this.path = java.path or error() + this.protocol = java.protocol or error() + this.headers = JavaLuan.toLuan(java.headers) + this.parameters = JavaLuan.toLuan(java.parameters) + this.cookies = JavaLuan.toLuan(java.cookies) + end + this.scheme = "http" + + function this.full_path() -- compatible with jetty + return this.raw_path or this.path + end + + function this.url() + return this.scheme.."://"..this.headers["host"]..this.raw_path + end + + return this +end + +local STATUS = { + OK = 200 + MOVED_PERMANENTLY = 301 + FOUND = 302 + -- add more as needed +} +Http.STATUS = STATUS + +function Http.new_response() + local this = {} + Http.response = this + + function this.reset() + this.java = Response.new() + this.headers = {} + this.status = STATUS.OK + this.writer = nil + end + + this.reset() + + function this.send_redirect(location) + this.reset() + this.status = STATUS.FOUND + this.headers["location"] = location + end + + function this.send_error(status,msg) + this.reset() + this.status = status + if msg ~= nil then + this.headers["content-type"] = "text/plain; charset=utf-8" + local writer = this.text_writer() + writer.write(msg) + end + end + + function this.set_cookie(name,value,attributes) + attributes = attributes or {} + local attrMap = HashMap.new() + for attr_name, attr_value in pairs(attributes) do + type(attr_name)=="string" or "cookie attribute name must be string" + type(attr_value)=="string" or "cookie attribute value must be string" + attrMap.put(attr_name,attr_value) + end + this.java.setCookie(name,value,attrMap) + end + + function this.set_persistent_cookie(name,value,attributes) + attributes = attributes or {} + attributes["Max-Age"] = "10000000" + this.set_cookie(name,value,attributes) + end + + function this.remove_cookie(name,attributes) + attributes = attributes or {} + attributes["Max-Age"] = "0" + this.set_cookie(name,"delete",attributes) + end + + function this.text_writer() + this.writer and "writer already set" + this.writer = ResponseOutputStream.new(this.java) + this.writer = OutputStreamWriter.new(this.writer) + return IoLuan.textWriter(this.writer) + end + + function this.binary_writer() + this.writer and "writer already set" + this.writer = ResponseOutputStream.new(this.java) + return IoLuan.binaryWriter(this.writer) + end + + return this +end + +function Http.finish() -- called only from java + local response = Http.response or error() + local java = response.java or error() + java.status = Status.getStatus(response.status) + for name, value in pairs(response.headers) do + type(name)=="string" or "header name must be string" + name = lower(name) + value = JavaLuan.toJava(value) + java.headers.put(name,value) + end + response.writer and response.writer.close() + return java +end + + +function Http.uncache_site() + for k in pairs(Table.copy(Package.loaded)) do + if matches(k,"^site:") then + Package.loaded[k] = nil + end + end +end + +return Http
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/http/HttpServicer.java Sun Feb 11 02:41:23 2018 -0700 @@ -0,0 +1,52 @@ +package luan.modules.http; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import luan.webserver.Request; +import luan.webserver.Response; +import luan.LuanState; +import luan.LuanFunction; +import luan.LuanException; +import luan.LuanTable; +import luan.LuanCloner; +import luan.modules.PackageLuan; + + +public final class HttpServicer { + private static final Logger logger = LoggerFactory.getLogger(HttpServicer.class); + + public static Response service(LuanState luan,Request request,String modName) + throws LuanException + { + LuanFunction fn; + synchronized(luan) { + PackageLuan.enableLoad(luan,"luan:http/Http.luan",modName); + LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http.luan"); + Object mod = PackageLuan.load(luan,modName); + if( mod.equals(Boolean.FALSE) ) + return null; + if( !(mod instanceof LuanFunction) ) + throw new LuanException( "module '"+modName+"' must return a function" ); + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + luan = (LuanState)cloner.clone(luan); + fn = (LuanFunction)cloner.get(mod); + } + + LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http.luan"); + + // request + LuanFunction newRequestFn = (LuanFunction)module.rawGet("new_request"); + newRequestFn.call( luan, new Object[]{request} ); + + // response + LuanFunction newResponseFn = (LuanFunction)module.rawGet("new_response"); + newResponseFn.call(luan); + + fn.call(luan); + + LuanFunction finishFn = (LuanFunction)module.rawGet("finish"); + Response response = (Response)finishFn.call(luan); + return response; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/http/LuanHandler.java Sun Feb 11 02:41:23 2018 -0700 @@ -0,0 +1,167 @@ +package luan.modules.http; + +import java.io.Writer; +import java.io.PrintWriter; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.BindException; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import luan.webserver.Request; +import luan.webserver.Response; +import luan.webserver.Server; +import luan.webserver.Handler; +import luan.webserver.Status; +import luan.webserver.ResponseOutputStream; +import luan.Luan; +import luan.LuanState; +import luan.LuanTable; +import luan.LuanFunction; +import luan.LuanJavaFunction; +import luan.LuanCloner; +import luan.LuanException; +import luan.modules.PackageLuan; + + +public class LuanHandler implements Handler { + private final LuanState luanInit; + private final Logger logger; + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private LuanState luan; + + private static final Method resetLuanMethod; + static { + try { + resetLuanMethod = LuanHandler.class.getMethod("reset_luan"); + } catch(NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + public LuanHandler(LuanState luan,String loggerRoot) { + this.luanInit = luan; + if( loggerRoot==null ) + loggerRoot = ""; + logger = LoggerFactory.getLogger(loggerRoot+LuanHandler.class.getName()); + try { + LuanTable Http = (LuanTable)PackageLuan.require(luanInit,"luan:http/Http.luan"); + Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) ); + } catch(LuanException e) { + throw new RuntimeException(e); + } + setLuan(); + } + + @Override public Response handle(Request request) { + if( request.path.endsWith("/") ) + return null; + String modName = "site:" + request.path +".luan"; + return handle(request,modName); + } + + Response handle(Request request,String modName) { + Thread thread = Thread.currentThread(); + String oldName = thread.getName(); + thread.setName(request.headers.get("host")+request.path); + lock.readLock().lock(); + try { + Response response = HttpServicer.service(luan,request,modName); + return response; + } catch(LuanException e) { +//e.printStackTrace(); + String err = e.getLuanStackTraceString(); + logger.error(err); + String msg = "Internel Server Error\n\n" + err; + return Response.errorResponse( Status.INTERNAL_SERVER_ERROR, msg ); + } finally { + lock.readLock().unlock(); + thread.setName(oldName); + } + } +/* + @Override protected void doStart() throws Exception { +// Thread.dumpStack(); +//System.out.println("qqqqqqqqqqqqqqqqqqqq doStart "+this); + setLuan(); + super.doStart(); + } + + @Override protected void doStop() throws Exception { + synchronized(luan) { + luan.close(); + } +//System.out.println("qqqqqqqqqqqqqqqqqqqq doStop "+this); + super.doStop(); + } +*/ + public Object call_rpc(String fnName,Object... args) throws LuanException { + lock.readLock().lock(); + try { + LuanFunction fn; + LuanState luan = this.luan; + synchronized(luan) { + PackageLuan.enableLoad(luan,"luan:Rpc.luan"); + LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan"); + LuanTable fns = (LuanTable)rpc.get(luan,"functions"); + fn = (LuanFunction)fns.get(luan,fnName); + if( fn == null ) + throw new LuanException( "function not found: " + fnName ); + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + luan = (LuanState)cloner.clone(luan); + fn = (LuanFunction)cloner.get(fn); + } + return fn.call(luan,args); + } finally { + lock.readLock().unlock(); + } + } + + public void reset_luan() { + new Thread() { + public void run() { + lock.writeLock().lock(); + try { + synchronized(luan) { + luan.close(); + setLuan(); + } + } catch(IOException e) { + logger.error("reset_luan failed",e); + } finally { + lock.writeLock().unlock(); + } + } + }.start(); + } + + private void setLuan() { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); + luan = (LuanState)cloner.clone(luanInit); + try { + PackageLuan.load(luan,"site:/init.luan"); + } catch(LuanException e) { + String err = e.getLuanStackTraceString(); + logger.error(err); + } + } + + public Object runLuan(String sourceText,String sourceName) throws LuanException { + LuanFunction fn = Luan.load(sourceText,sourceName); + synchronized(luan) { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); + LuanState luan = (LuanState)cloner.clone(this.luan); + return fn.call(luan); + } + } + + public static void start(Server server) throws Exception { + try { + server.start(); + } catch(BindException e) { + throw new LuanException(e.toString()); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/http/NotFound.java Sun Feb 11 02:41:23 2018 -0700 @@ -0,0 +1,19 @@ +package luan.modules.http; + +import luan.webserver.Request; +import luan.webserver.Response; +import luan.webserver.Handler; + + +public class NotFound implements Handler { + private final LuanHandler luanHandler; + + public NotFound(LuanHandler luanHandler) { + this.luanHandler = luanHandler; + } + + @Override public Response handle(Request request) { + return luanHandler.handle(request,"site:/not_found.luan"); + } + +}
--- a/src/luan/modules/http/Server.luan Sun Feb 11 02:34:35 2018 -0700 +++ b/src/luan/modules/http/Server.luan Sun Feb 11 02:41:23 2018 -0700 @@ -1,1 +1,78 @@ -return require "luan:http/impl/Server.luan" +local Luan = require "luan:Luan.luan" +local error = Luan.error +local String = require "luan:String.luan" +local gsub = String.gsub or error() +local match = String.match or error() +local matches = String.matches or error() +local Io = require "luan:Io.luan" +local Package = require "luan:Package.luan" +local Rpc = require "luan:Rpc.luan" +local Thread = require "luan:Thread.luan" +local Http = require "luan:http/Http.luan" +require "luan:logging/init.luan" -- initialize logging +local Logging = require "luan:logging/Logging.luan" +local logger = Logging.logger "http/Server" + +java() +local JavaServer = require "java:luan.webserver.Server" +local FileHandler = require "java:luan.webserver.handlers.FileHandler" +local DirHandler = require "java:luan.webserver.handlers.DirHandler" +local IndexHandler = require "java:luan.webserver.handlers.IndexHandler" +local ContentTypeHandler = require "java:luan.webserver.handlers.ContentTypeHandler" +local SafeHandler = require "java:luan.webserver.handlers.SafeHandler" +local LogHandler = require "java:luan.webserver.handlers.LogHandler" +local ListHandler = require "java:luan.webserver.handlers.ListHandler" +local LuanHandler = require "java:luan.modules.http.LuanHandler" +local NotFound = require "java:luan.modules.http.NotFound" + + +local Server = {} + +Server.port = 8080 + +function Server.init(dir) + local dir_uri, dir_path + if matches(dir,":") then + dir_uri = dir + dir_path = match(dir,"^file:(.*)$") or error "server dir must be scheme 'file:'" + else + dir_path = dir + dir_uri = "file:"..dir + end + dir_uri = gsub(dir_uri,"/$","") -- remove trailing '/' if any + Http.dir = dir_uri + function Io.schemes.site(path) + return Io.uri( dir_uri..path ) + end + local file_handler = FileHandler.new(dir_path) + local dir_handler = DirHandler.new(file_handler) + local luan_handler = LuanHandler.new() + local not_found_hander = NotFound.new(luan_handler) + local handler = ListHandler.new( luan_handler, file_handler ) + handler = IndexHandler.new(handler) + handler = ListHandler.new( handler, dir_handler, not_found_hander ) + handler = ContentTypeHandler.new(handler) + handler = SafeHandler.new(handler) + handler = LogHandler.new(handler) + Server.server = JavaServer.new(Server.port,handler) +end + +function Server.start() + LuanHandler.start(Server.server) +end + +function Server.start_rpc() + function Rpc.functions.call(domain,fn_name,...) + return Server.luan_handler.call_rpc(fn_name,...) + end + + Thread.fork(Rpc.serve) +end + +function Server.serve(dir) + Server.init(dir) + Server.start_rpc() + Server.start() +end + +return Server
--- a/src/luan/modules/http/impl/Http.luan Sun Feb 11 02:34:35 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -java() -local Luan = require "luan:Luan.luan" -local error = Luan.error -local ipairs = Luan.ipairs or error() -local pairs = Luan.pairs or error() -local type = Luan.type or error() -local Io = require "luan:Io.luan" -local Html = require "luan:Html.luan" -local url_encode = Html.url_encode or error() -local Table = require "luan:Table.luan" -local clear = Table.clear or error() -local Package = require "luan:Package.luan" -local String = require "luan:String.luan" -local lower = String.lower or error() -local matches = String.matches or error() -local HttpServicer = require "java:luan.modules.http.impl.HttpServicer" -local IoLuan = require "java:luan.modules.IoLuan" -local JavaLuan = require "java:luan.Luan" -local Response = require "java:luan.webserver.Response" -local ResponseOutputStream = require "java:luan.webserver.ResponseOutputStream" -local Status = require "java:luan.webserver.Status" -local OutputStreamWriter = require "java:java.io.OutputStreamWriter" -local HashMap = require "java:java.util.HashMap" - - -local Http = {} - -Http.version = "impl" - -function Http.new_request(java) - local this = {} - Http.request = this - if java == nil then - this.method = "GET" - this.headers = {} - this.parameters = {} - this.cookies = {} - else - this.java = java - this.method = java.method or error() - this.raw_path = java.rawPath or error() - this.path = java.path or error() - this.protocol = java.protocol or error() - this.headers = JavaLuan.toLuan(java.headers) - this.parameters = JavaLuan.toLuan(java.parameters) - this.cookies = JavaLuan.toLuan(java.cookies) - end - this.scheme = "http" - - function this.full_path() -- compatible with jetty - return this.raw_path or this.path - end - - function this.url() - return this.scheme.."://"..this.headers["host"]..this.raw_path - end - - return this -end - -local STATUS = { - OK = 200 - MOVED_PERMANENTLY = 301 - FOUND = 302 - -- add more as needed -} -Http.STATUS = STATUS - -function Http.new_response() - local this = {} - Http.response = this - - function this.reset() - this.java = Response.new() - this.headers = {} - this.status = STATUS.OK - this.writer = nil - end - - this.reset() - - function this.send_redirect(location) - this.reset() - this.status = STATUS.FOUND - this.headers["location"] = location - end - - function this.send_error(status,msg) - this.reset() - this.status = status - if msg ~= nil then - this.headers["content-type"] = "text/plain; charset=utf-8" - local writer = this.text_writer() - writer.write(msg) - end - end - - function this.set_cookie(name,value,attributes) - attributes = attributes or {} - local attrMap = HashMap.new() - for attr_name, attr_value in pairs(attributes) do - type(attr_name)=="string" or "cookie attribute name must be string" - type(attr_value)=="string" or "cookie attribute value must be string" - attrMap.put(attr_name,attr_value) - end - this.java.setCookie(name,value,attrMap) - end - - function this.set_persistent_cookie(name,value,attributes) - attributes = attributes or {} - attributes["Max-Age"] = "10000000" - this.set_cookie(name,value,attributes) - end - - function this.remove_cookie(name,attributes) - attributes = attributes or {} - attributes["Max-Age"] = "0" - this.set_cookie(name,"delete",attributes) - end - - function this.text_writer() - this.writer and "writer already set" - this.writer = ResponseOutputStream.new(this.java) - this.writer = OutputStreamWriter.new(this.writer) - return IoLuan.textWriter(this.writer) - end - - function this.binary_writer() - this.writer and "writer already set" - this.writer = ResponseOutputStream.new(this.java) - return IoLuan.binaryWriter(this.writer) - end - - return this -end - -function Http.finish() -- called only from java - local response = Http.response or error() - local java = response.java or error() - java.status = Status.getStatus(response.status) - for name, value in pairs(response.headers) do - type(name)=="string" or "header name must be string" - name = lower(name) - value = JavaLuan.toJava(value) - java.headers.put(name,value) - end - response.writer and response.writer.close() - return java -end - - -function Http.uncache_site() - for k in pairs(Table.copy(Package.loaded)) do - if matches(k,"^site:") then - Package.loaded[k] = nil - end - end -end - -return Http
--- a/src/luan/modules/http/impl/HttpServicer.java Sun Feb 11 02:34:35 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -package luan.modules.http.impl; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import luan.webserver.Request; -import luan.webserver.Response; -import luan.LuanState; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanTable; -import luan.LuanCloner; -import luan.modules.PackageLuan; - - -public final class HttpServicer { - private static final Logger logger = LoggerFactory.getLogger(HttpServicer.class); - - public static Response service(LuanState luan,Request request,String modName) - throws LuanException - { - LuanFunction fn; - synchronized(luan) { - PackageLuan.enableLoad(luan,"luan:http/Http.luan",modName); - LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http.luan"); - Object mod = PackageLuan.load(luan,modName); - if( mod.equals(Boolean.FALSE) ) - return null; - if( !(mod instanceof LuanFunction) ) - throw new LuanException( "module '"+modName+"' must return a function" ); - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (LuanState)cloner.clone(luan); - fn = (LuanFunction)cloner.get(mod); - } - - LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http.luan"); - - // request - LuanFunction newRequestFn = (LuanFunction)module.rawGet("new_request"); - newRequestFn.call( luan, new Object[]{request} ); - - // response - LuanFunction newResponseFn = (LuanFunction)module.rawGet("new_response"); - newResponseFn.call(luan); - - fn.call(luan); - - LuanFunction finishFn = (LuanFunction)module.rawGet("finish"); - Response response = (Response)finishFn.call(luan); - return response; - } - -}
--- a/src/luan/modules/http/impl/LuanHandler.java Sun Feb 11 02:34:35 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,167 +0,0 @@ -package luan.modules.http.impl; - -import java.io.Writer; -import java.io.PrintWriter; -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.BindException; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import luan.webserver.Request; -import luan.webserver.Response; -import luan.webserver.Server; -import luan.webserver.Handler; -import luan.webserver.Status; -import luan.webserver.ResponseOutputStream; -import luan.Luan; -import luan.LuanState; -import luan.LuanTable; -import luan.LuanFunction; -import luan.LuanJavaFunction; -import luan.LuanCloner; -import luan.LuanException; -import luan.modules.PackageLuan; - - -public class LuanHandler implements Handler { - private final LuanState luanInit; - private final Logger logger; - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private LuanState luan; - - private static final Method resetLuanMethod; - static { - try { - resetLuanMethod = LuanHandler.class.getMethod("reset_luan"); - } catch(NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - - public LuanHandler(LuanState luan,String loggerRoot) { - this.luanInit = luan; - if( loggerRoot==null ) - loggerRoot = ""; - logger = LoggerFactory.getLogger(loggerRoot+LuanHandler.class.getName()); - try { - LuanTable Http = (LuanTable)PackageLuan.require(luanInit,"luan:http/Http.luan"); - Http.rawPut( "reset_luan", new LuanJavaFunction(resetLuanMethod,this) ); - } catch(LuanException e) { - throw new RuntimeException(e); - } - setLuan(); - } - - @Override public Response handle(Request request) { - if( request.path.endsWith("/") ) - return null; - String modName = "site:" + request.path +".luan"; - return handle(request,modName); - } - - Response handle(Request request,String modName) { - Thread thread = Thread.currentThread(); - String oldName = thread.getName(); - thread.setName(request.headers.get("host")+request.path); - lock.readLock().lock(); - try { - Response response = HttpServicer.service(luan,request,modName); - return response; - } catch(LuanException e) { -//e.printStackTrace(); - String err = e.getLuanStackTraceString(); - logger.error(err); - String msg = "Internel Server Error\n\n" + err; - return Response.errorResponse( Status.INTERNAL_SERVER_ERROR, msg ); - } finally { - lock.readLock().unlock(); - thread.setName(oldName); - } - } -/* - @Override protected void doStart() throws Exception { -// Thread.dumpStack(); -//System.out.println("qqqqqqqqqqqqqqqqqqqq doStart "+this); - setLuan(); - super.doStart(); - } - - @Override protected void doStop() throws Exception { - synchronized(luan) { - luan.close(); - } -//System.out.println("qqqqqqqqqqqqqqqqqqqq doStop "+this); - super.doStop(); - } -*/ - public Object call_rpc(String fnName,Object... args) throws LuanException { - lock.readLock().lock(); - try { - LuanFunction fn; - LuanState luan = this.luan; - synchronized(luan) { - PackageLuan.enableLoad(luan,"luan:Rpc.luan"); - LuanTable rpc = (LuanTable)PackageLuan.require(luan,"luan:Rpc.luan"); - LuanTable fns = (LuanTable)rpc.get(luan,"functions"); - fn = (LuanFunction)fns.get(luan,fnName); - if( fn == null ) - throw new LuanException( "function not found: " + fnName ); - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - luan = (LuanState)cloner.clone(luan); - fn = (LuanFunction)cloner.get(fn); - } - return fn.call(luan,args); - } finally { - lock.readLock().unlock(); - } - } - - public void reset_luan() { - new Thread() { - public void run() { - lock.writeLock().lock(); - try { - synchronized(luan) { - luan.close(); - setLuan(); - } - } catch(IOException e) { - logger.error("reset_luan failed",e); - } finally { - lock.writeLock().unlock(); - } - } - }.start(); - } - - private void setLuan() { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); - luan = (LuanState)cloner.clone(luanInit); - try { - PackageLuan.load(luan,"site:/init.luan"); - } catch(LuanException e) { - String err = e.getLuanStackTraceString(); - logger.error(err); - } - } - - public Object runLuan(String sourceText,String sourceName) throws LuanException { - LuanFunction fn = Luan.load(sourceText,sourceName); - synchronized(luan) { - LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL); - LuanState luan = (LuanState)cloner.clone(this.luan); - return fn.call(luan); - } - } - - public static void start(Server server) throws Exception { - try { - server.start(); - } catch(BindException e) { - throw new LuanException(e.toString()); - } - } - -}
--- a/src/luan/modules/http/impl/NotFound.java Sun Feb 11 02:34:35 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package luan.modules.http.impl; - -import luan.webserver.Request; -import luan.webserver.Response; -import luan.webserver.Handler; - - -public class NotFound implements Handler { - private final LuanHandler luanHandler; - - public NotFound(LuanHandler luanHandler) { - this.luanHandler = luanHandler; - } - - @Override public Response handle(Request request) { - return luanHandler.handle(request,"site:/not_found.luan"); - } - -}
--- a/src/luan/modules/http/impl/Server.luan Sun Feb 11 02:34:35 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -local Luan = require "luan:Luan.luan" -local error = Luan.error -local String = require "luan:String.luan" -local gsub = String.gsub or error() -local match = String.match or error() -local matches = String.matches or error() -local Io = require "luan:Io.luan" -local Package = require "luan:Package.luan" -local Rpc = require "luan:Rpc.luan" -local Thread = require "luan:Thread.luan" -local Http = require "luan:http/Http.luan" -require "luan:logging/init.luan" -- initialize logging -local Logging = require "luan:logging/Logging.luan" -local logger = Logging.logger "http/Server" - -java() -local JavaServer = require "java:luan.webserver.Server" -local FileHandler = require "java:luan.webserver.handlers.FileHandler" -local DirHandler = require "java:luan.webserver.handlers.DirHandler" -local IndexHandler = require "java:luan.webserver.handlers.IndexHandler" -local ContentTypeHandler = require "java:luan.webserver.handlers.ContentTypeHandler" -local SafeHandler = require "java:luan.webserver.handlers.SafeHandler" -local LogHandler = require "java:luan.webserver.handlers.LogHandler" -local ListHandler = require "java:luan.webserver.handlers.ListHandler" -local LuanHandler = require "java:luan.modules.http.impl.LuanHandler" -local NotFound = require "java:luan.modules.http.impl.NotFound" - - -local Server = {} - -Server.port = 8080 - -function Server.init(dir) - local dir_uri, dir_path - if matches(dir,":") then - dir_uri = dir - dir_path = match(dir,"^file:(.*)$") or error "server dir must be scheme 'file:'" - else - dir_path = dir - dir_uri = "file:"..dir - end - dir_uri = gsub(dir_uri,"/$","") -- remove trailing '/' if any - Http.dir = dir_uri - function Io.schemes.site(path) - return Io.uri( dir_uri..path ) - end - local file_handler = FileHandler.new(dir_path) - local dir_handler = DirHandler.new(file_handler) - local luan_handler = LuanHandler.new() - local not_found_hander = NotFound.new(luan_handler) - local handler = ListHandler.new( luan_handler, file_handler ) - handler = IndexHandler.new(handler) - handler = ListHandler.new( handler, dir_handler, not_found_hander ) - handler = ContentTypeHandler.new(handler) - handler = SafeHandler.new(handler) - handler = LogHandler.new(handler) - Server.server = JavaServer.new(Server.port,handler) -end - -function Server.start() - LuanHandler.start(Server.server) -end - -function Server.start_rpc() - function Rpc.functions.call(domain,fn_name,...) - return Server.luan_handler.call_rpc(fn_name,...) - end - - Thread.fork(Rpc.serve) -end - -function Server.serve(dir) - Server.init(dir) - Server.start_rpc() - Server.start() -end - -return Server