Mercurial Hosting > luan
changeset 1315:5763597ca5c0
add DomainHandler
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 30 Jan 2019 01:21:49 -0700 |
parents | 51a1987b55a3 |
children | 11d3640e739d |
files | conv.txt src/luan/host/Init.luan src/luan/host/WebHandler.java src/luan/host/run.luan src/luan/modules/http/Http.luan src/luan/modules/http/LuanDomainHandler.java src/luan/modules/http/Server.luan src/luan/modules/url/LuanUrl.java src/luan/webserver/handlers/DomainHandler.java |
diffstat | 9 files changed, 194 insertions(+), 103 deletions(-) [+] |
line wrap: on
line diff
--- a/conv.txt Tue Jan 29 19:10:39 2019 -0700 +++ b/conv.txt Wed Jan 30 01:21:49 2019 -0700 @@ -1,3 +1,5 @@ +Hosting.domain + Thread.fork Io.output_to Io.output_of
--- a/src/luan/host/Init.luan Tue Jan 29 19:10:39 2019 -0700 +++ b/src/luan/host/Init.luan Wed Jan 30 01:21:49 2019 -0700 @@ -72,7 +72,7 @@ return Io.uri( Http.dir..path, loading ) end -Hosting.domain = domain +Http.domain = domain Io.password = Init.password
--- a/src/luan/host/WebHandler.java Tue Jan 29 19:10:39 2019 -0700 +++ b/src/luan/host/WebHandler.java Wed Jan 30 01:21:49 2019 -0700 @@ -1,70 +1,42 @@ package luan.host; import java.io.File; -import java.io.IOException; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -//import java.lang.ref.WeakReference; -import java.lang.ref.ReferenceQueue; -import java.util.Map; -import java.util.HashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import luan.webserver.Handler; -import luan.webserver.Server; import luan.webserver.Request; import luan.webserver.Response; -import luan.webserver.handlers.IndexHandler; -import luan.webserver.handlers.ListHandler; -import luan.Luan; +import luan.webserver.handlers.DomainHandler; import luan.LuanState; import luan.LuanException; import luan.LuanTable; -import luan.LuanFunction; import luan.modules.IoLuan; import luan.modules.JavaLuan; -import luan.modules.PackageLuan; import luan.modules.http.LuanHandler; public class WebHandler implements Handler { private static final Logger logger = LoggerFactory.getLogger(WebHandler.class); - private static class LuanRef { - private final Handler handler; - private final LuanHandler luanHandler; - - private LuanRef(Handler handler,LuanHandler luanHandler) { - this.handler = handler; - this.luanHandler = luanHandler; - } - } - - private static final ReferenceQueue<LuanRef> queue = new ReferenceQueue<LuanRef>(); - - private static class MyReference extends SoftReference<LuanRef> { - private LuanHandler luanHandler; + private static final DomainHandler.Factory factory = new DomainHandler.Factory() { + public Handler newHandler(String domain) { + File dir = new File(sitesDir,domain); + if( !dir.exists() /* && !recover(dir) */ ) + return null; + String dirStr = dir.toString(); - private MyReference(LuanRef lr) { - super(lr,queue); - this.luanHandler = lr.luanHandler; - } - } + String logDir = dirStr + "/site/private/local/logs/web"; + new File(logDir).mkdirs(); - private static void sweep() { - while(true) { - MyReference ref = (MyReference)queue.poll(); - if( ref == null ) - return; - //logger.info("sweep"); - ref.luanHandler.close(); - ref.luanHandler = null; + LuanState luan = new LuanState(); + LuanTable init = initLuan(luan,dirStr,domain); + String loggerRoot = (String)init.rawGet("logger_root"); + return new LuanHandler(luan,loggerRoot); } - } - + }; public static String allowJavaFileName = "allow_java"; // change for security - private static final Map<String,MyReference> siteMap = new HashMap<String,MyReference>(); + private static final DomainHandler domainHandler = new DomainHandler(factory); private static String sitesDir = null; public static boolean isServing() { @@ -79,45 +51,20 @@ sitesDir = dir; } - public Response handle(Request request) { - String host = (String)request.headers.get("host"); - int i = host.indexOf(':'); - String domain = i == -1 ? host : host.substring(0,i); -// System.out.println("handle "+domain); - LuanRef lr = getSite(domain); - if( lr == null ) - return null; - return lr.handler.handle(request); + @Override public Response handle(Request request) { + return domainHandler.handle(request); } public static Object runLuan(String domain,String sourceText,String sourceName) throws LuanException { - LuanRef lr = getSite(domain); - return lr.luanHandler.runLuan(sourceText,sourceName); + LuanHandler luanHandler = (LuanHandler)domainHandler.getHandler(domain); + return luanHandler.runLuan(sourceText,sourceName); } public static Object callSite(String domain,String fnName,Object... args) throws LuanException { - LuanRef lr = getSite(domain); - return lr.luanHandler.call_rpc(fnName,args); + LuanHandler luanHandler = (LuanHandler)domainHandler.getHandler(domain); + return luanHandler.call_rpc(fnName,args); } - private static LuanRef getSite(String domain) { - synchronized(siteMap) { - Reference<LuanRef> ref = siteMap.get(domain); - LuanRef lr = ref==null ? null : ref.get(); - if( lr == null ) { - //if(ref!=null) logger.info("gc "+domain); - if( sitesDir==null ) - throw new NullPointerException("sitesDir"); - File dir = new File(sitesDir,domain); - if( !dir.exists() /* && !recover(dir) */ ) - return null; - sweep(); - lr = newSite(dir.toString(),domain); - siteMap.put(domain,new MyReference(lr)); - } - return lr; - } - } /* private static boolean recover(File dir) { File backups = new File(dir.getParentFile().getParentFile(),"backups"); @@ -157,34 +104,12 @@ return init; } - private static LuanRef newSite(String dir,String domain) { - LuanState luan = new LuanState(); - LuanTable init = initLuan(luan,dir,domain); - - String loggerRoot = (String)init.rawGet("logger_root"); - LuanHandler luanHandler = new LuanHandler(luan,loggerRoot); - - Handler handler = luanHandler; - handler = new IndexHandler(handler); - - String logDir = dir + "/site/private/local/logs/web"; - new File(logDir).mkdirs(); - - return new LuanRef(handler,luanHandler); - } - - public static void removeHandler(String domain) throws Exception { - synchronized(siteMap) { - Reference<LuanRef> ref = siteMap.remove(domain); - LuanRef lr = ref==null ? null : ref.get(); - if( lr != null ) { - lr.luanHandler.close(); - } - } + public static void removeHandler(String domain) { + domainHandler.removeHandler(domain); } public static void loadHandler(String domain) { - getSite(domain); + domainHandler.getHandler(domain); } private static final IoLuan.Security ioSecurity(String dir) {
--- a/src/luan/host/run.luan Tue Jan 29 19:10:39 2019 -0700 +++ b/src/luan/host/run.luan Wed Jan 30 01:21:49 2019 -0700 @@ -20,11 +20,13 @@ -- web server local Server = require "java:luan.webserver.Server" +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 webHandler = WebHandler.new(Hosting.sites_dir) local handler = webHandler +handler = IndexHandler.new(handler) handler = ContentTypeHandler.new(handler) handler = SafeHandler.new(handler) local server = Server.ForAddress.new("127.0.0.1",8080,handler)
--- a/src/luan/modules/http/Http.luan Tue Jan 29 19:10:39 2019 -0700 +++ b/src/luan/modules/http/Http.luan Wed Jan 30 01:21:49 2019 -0700 @@ -172,4 +172,6 @@ return Response.errorResponse( Status.INTERNAL_SERVER_ERROR, msg ) end +Http.domain = nil -- set in domain specific cases + return Http
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/modules/http/LuanDomainHandler.java Wed Jan 30 01:21:49 2019 -0700 @@ -0,0 +1,41 @@ +package luan.modules.http; + +import luan.webserver.Request; +import luan.webserver.Response; +import luan.webserver.Handler; +import luan.webserver.handlers.DomainHandler; +import luan.LuanState; +import luan.LuanTable; +import luan.LuanCloner; +import luan.LuanException; + + +public final class LuanDomainHandler implements Handler { + + private final LuanState luanInit; + + private final DomainHandler.Factory factory = new DomainHandler.Factory() { + public Handler newHandler(String domain) { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); + LuanState luan = (LuanState)cloner.clone(luanInit); + try { + LuanTable Http = (LuanTable)luan.require("luan:http/Http.luan"); + Http.put( "domain", domain ); + } catch(LuanException e) { + throw new RuntimeException(e); + } + return new LuanHandler(luan,null); + } + }; + + private final DomainHandler domainHandler = new DomainHandler(factory); + + public LuanDomainHandler(LuanState luanInit) { + LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE); + this.luanInit = (LuanState)cloner.clone(luanInit); + } + + @Override public Response handle(Request request) { + return domainHandler.handle(request); + } +}
--- a/src/luan/modules/http/Server.luan Tue Jan 29 19:10:39 2019 -0700 +++ b/src/luan/modules/http/Server.luan Wed Jan 30 01:21:49 2019 -0700 @@ -6,6 +6,7 @@ local matches = String.matches or error() local try = Luan.try or error() local Io = require "luan:Io.luan" +local uri = Io.uri or error() local Package = require "luan:Package.luan" local Rpc = require "luan:Rpc.luan" local Thread = require "luan:Thread.luan" @@ -35,7 +36,7 @@ dir = gsub(dir,"/$","") -- remove trailing '/' if any Http.dir = dir function Io.schemes.site(path) - return Io.uri( dir..path ) + return uri( dir..path ) end end @@ -77,10 +78,11 @@ return server, luan_handler end -function Server.serve_for_proxy(dir,port) +function Server.serve_for_proxy(dir,port,LuanHandlerClass) port = port or 8080 + LuanHandlerClass = LuanHandlerClass or LuanHandler Server.init_dir(dir) - local luan_handler = LuanHandler.new() + local luan_handler = LuanHandlerClass.new() local handler = IndexHandler.new(luan_handler) handler = ContentTypeHandler.new(handler) handler = SafeHandler.new(handler)
--- a/src/luan/modules/url/LuanUrl.java Tue Jan 29 19:10:39 2019 -0700 +++ b/src/luan/modules/url/LuanUrl.java Wed Jan 30 01:21:49 2019 -0700 @@ -5,6 +5,7 @@ import java.io.OutputStream; import java.io.Reader; import java.io.IOException; +import java.io.FileNotFoundException; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLConnection; @@ -253,6 +254,8 @@ private static InputStream getInputStream(LuanState luan,HttpURLConnection httpCon) throws IOException, LuanException { try { return httpCon.getInputStream(); + } catch(FileNotFoundException e) { + throw e; } catch(IOException e) { int responseCode = httpCon.getResponseCode(); String responseMessage = httpCon.getResponseMessage();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/luan/webserver/handlers/DomainHandler.java Wed Jan 30 01:21:49 2019 -0700 @@ -0,0 +1,114 @@ +package luan.webserver.handlers; + +import java.io.Closeable; +import java.io.IOException; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.ReferenceQueue; +import java.util.Map; +import java.util.HashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import luan.webserver.Handler; +import luan.webserver.Request; +import luan.webserver.Response; + + +public final class DomainHandler implements Handler { + private static final Logger logger = LoggerFactory.getLogger(DomainHandler.class); + + public interface Factory { + public Handler newHandler(String domain); + } + + private static class Ref { + private final Handler handler; + + private Ref(Handler handler) { + this.handler = handler; + } + } + + private final ReferenceQueue<Ref> queue = new ReferenceQueue<Ref>(); + + private class MyReference extends SoftReference<Ref> { + private Handler handler; + + private MyReference(Ref r) { + super(r,queue); + this.handler = r.handler; + } + } + + private static void close(Handler handler) { + if( handler instanceof Closeable ) { + try { + ((Closeable)handler).close(); + } catch(IOException e) { + logger.error(handler.toString(),e); + } + } + } + + private void sweep() { + while(true) { + MyReference ref = (MyReference)queue.poll(); + if( ref == null ) + return; + //logger.info("sweep"); + close(ref.handler); + ref.handler = null; + } + } + + private final Map<String,MyReference> map = new HashMap<String,MyReference>(); + + private final Factory factory; + + public DomainHandler(Factory factory) { + this.factory = factory; + } + + public Response handle(Request request) { + String host = (String)request.headers.get("host"); + int i = host.indexOf(':'); + String domain = i == -1 ? host : host.substring(0,i); + Handler handler = getHandler(domain); + return handler==null ? null : handler.handle(request); + } + + public Handler getHandler(String domain) { + Ref r = getRef(domain); + return r==null ? null : r.handler; + } + + public void removeHandler(String domain) { + domain = domain.toLowerCase(); + synchronized(map) { + Reference<Ref> ref = map.remove(domain); + Ref r = ref==null ? null : ref.get(); + if( r != null ) { + close(r.handler); + } + } + } + + private Ref getRef(String domain) { + domain = domain.toLowerCase(); + synchronized(map) { + Reference<Ref> ref = map.get(domain); + Ref r = ref==null ? null : ref.get(); + if( r == null ) { + //if(ref!=null) logger.info("gc "+domain); + sweep(); + Handler handler = factory.newHandler(domain); + if( handler == null ) + return null; + r = new Ref(handler); + map.put(domain,new MyReference(r)); + } + return r; + } + } + +}