Mercurial Hosting > luan
view src/luan/host/WebHandler.java @ 1148:49fb4e83484f
webserver - change headers to lower case
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 04 Feb 2018 17:11:06 -0700 |
parents | d30d400fd43d |
children | bdf27aa2a65c |
line wrap: on
line source
package luan.host; import java.io.File; import java.io.IOException; import java.util.Map; import java.util.HashMap; import java.util.TimeZone; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.NCSARequestLog; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ResourceHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerCollection; import luan.Luan; 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.jetty.LuanHandler; import luan.modules.http.jetty.AuthenticationHandler; import luan.modules.http.jetty.NotFound; public class WebHandler extends AbstractHandler { private static final Logger logger = LoggerFactory.getLogger(WebHandler.class); private static class Site { final Handler handler; final LuanHandler luanHandler; Site(Handler handler,LuanHandler luanHandler) { this.handler = handler; this.luanHandler = luanHandler; } } public static String allowJavaFileName = "allow_java"; // change for security private static final String tz = TimeZone.getDefault().getID(); private static final Map<String,Site> siteMap = new HashMap<String,Site>(); private static String sitesDir = null; private static Server server = null; public static boolean isServing() { return sitesDir != null; } public WebHandler(String dir,Server server) { if( sitesDir != null ) throw new RuntimeException("already set"); if( !new File(dir).exists() ) throw new RuntimeException(); this.sitesDir = dir; this.server = server; } public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException { String domain = baseRequest.getServerName(); // System.out.println("handle "+domain); Site site = getSite(domain); if( site != null ) { site.handler.handle(target,baseRequest,request,response); } } public static Object runLuan(String domain,String sourceText,String sourceName) throws LuanException { return getSite(domain).luanHandler.runLuan(sourceText,sourceName); } public static Object callSite(String domain,String fnName,Object... args) throws LuanException { return getSite(domain).luanHandler.call_rpc(fnName,args); } private static Site getSite(String domain) { synchronized(siteMap) { Site site = siteMap.get(domain); if( site == null ) { if( sitesDir==null ) throw new NullPointerException("sitesDir"); File dir = new File(sitesDir,domain); if( !dir.exists() /* && !recover(dir) */ ) return null; site = newSite(dir.toString(),domain); siteMap.put(domain,site); } return site; } } /* private static boolean recover(File dir) { File backups = new File(dir.getParentFile().getParentFile(),"backups"); if( !backups.exists() ) return false; String name = dir.getName(); File from = null; for( File backup : backups.listFiles() ) { File d = new File(backup,"current/"+name); if( d.exists() && (from==null || from.lastModified() < d.lastModified()) ) from = d; } if( from == null ) return false; if( !from.renameTo(dir) ) throw new RuntimeException("couldn't rename "+from+" to "+dir); logger.info("recovered "+name+" from "+from); return true; } */ static LuanTable initLuan(LuanState luan,String dir,String domain) { LuanTable init; try { init = (LuanTable)luan.eval( "local Luan = require 'luan:Luan.luan'\n" +"local f = Luan.load_file 'classpath:luan/host/Init.luan'\n" +"return f('"+dir+"','"+domain+"')\n" ); } catch(LuanException e) { throw new RuntimeException(e); } File allowJavaFile = new File(dir,"site/private/"+allowJavaFileName); if( !allowJavaFile.exists() ) { JavaLuan.setSecurity( luan, javaSecurity ); IoLuan.setSecurity( luan, ioSecurity(dir) ); } return init; } private static Site newSite(String dir,String domain) { LuanState luan = new LuanState(); LuanTable init = initLuan(luan,dir,domain); String password = (String)init.rawGet("password"); AuthenticationHandler authenticationHandler = new AuthenticationHandler("/private/"); authenticationHandler.setPassword(password); String loggerRoot = (String)init.rawGet("logger_root"); LuanHandler luanHandler = new LuanHandler(luan,loggerRoot); ResourceHandler resourceHandler = new ResourceHandler(); resourceHandler.setResourceBase(dir+"/site"); resourceHandler.setDirectoriesListed(true); resourceHandler.setAliases(true); NotFound notFoundHandler = new NotFound(luanHandler); DefaultHandler defaultHandler = new DefaultHandler(); HandlerList handlers = new HandlerList(); handlers.setHandlers(new Handler[]{authenticationHandler,luanHandler,resourceHandler,notFoundHandler,defaultHandler}); String logDir = dir+"/site/private/local/logs/web"; new File(logDir).mkdirs(); NCSARequestLog log = new NCSARequestLog(logDir+"/yyyy_mm_dd.log"); log.setExtended(false); log.setLogTimeZone(tz); RequestLogHandler logHandler = new RequestLogHandler(); logHandler.setRequestLog(log); HandlerCollection hc = new HandlerCollection(); hc.setHandlers(new Handler[]{handlers,logHandler}); // hc.setServer(getServer()); try { hc.start(); } catch(Exception e) { throw new RuntimeException(e); } return new Site(hc,luanHandler); } public static void removeHandler(String domain) throws Exception { synchronized(siteMap) { Site site = siteMap.remove(domain); if( site != null ) { site.handler.stop(); site.handler.destroy(); } } } public static void loadHandler(String domain) { getSite(domain); } public static Server server() { return server; } private static final IoLuan.Security ioSecurity(String dir) { final String siteDir = dir + "/site/"; return new IoLuan.Security() { public void check(LuanState luan,String name) throws LuanException { if( name.startsWith("file:") ) { if( name.contains("..") ) throw new LuanException("Security violation - '"+name+"' contains '..'"); if( !name.startsWith("file:"+siteDir) ) throw new LuanException("Security violation - '"+name+"' outside of site dir"); } else if( name.startsWith("classpath:luan/host/") ) { throw new LuanException("Security violation"); } else if( name.startsWith("os:") || name.startsWith("bash:") ) { throw new LuanException("Security violation"); } } }; } private static final JavaLuan.Security javaSecurity = new JavaLuan.Security() { public void check(LuanState luan,String name) throws LuanException { if( !name.startsWith("luan:") ) throw new LuanException("Security violation - only luan:* modules can load Java"); if( name.equals("luan:logging/Logging") ) throw new LuanException("Security violation - cannot reload Logging"); } }; }