Mercurial Hosting > luan
changeset 1211:f67628bd3582
remove jetty
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 12 Mar 2018 16:32:55 -0600 |
parents | 3db95cc00d09 |
children | 220228bf1af9 |
files | lib/jetty-continuation-8.1.15.v20140411.jar lib/jetty-http-8.1.15.v20140411.jar lib/jetty-io-8.1.15.v20140411.jar lib/jetty-server-8.1.15.v20140411.jar lib/jetty-util-8.1.15.v20140411.jar lib/servlet-api-3.0.jar src/luan/host/jetty/Backup.java src/luan/host/jetty/Init.luan src/luan/host/jetty/WebHandler.java src/luan/host/jetty/run.luan src/luan/modules/http/jetty/AuthenticationHandler.java src/luan/modules/http/jetty/Http.luan src/luan/modules/http/jetty/HttpServicer.java src/luan/modules/http/jetty/LuanHandler.java src/luan/modules/http/jetty/NotFound.java src/luan/modules/http/jetty/Server.luan src/luan/modules/http/jetty/serve.luan |
diffstat | 17 files changed, 0 insertions(+), 1266 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/host/jetty/Backup.java Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -package luan.host.jetty; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.lucene.index.SnapshotDeletionPolicy; -import org.apache.lucene.index.IndexCommit; -import org.apache.lucene.store.FSDirectory; -import luan.LuanState; -import luan.LuanTable; -import luan.LuanException; -import luan.modules.PackageLuan; -import luan.modules.lucene.LuceneIndex; -import luan.host.Log4j; - - -public final class Backup { - private static final Logger logger = LoggerFactory.getLogger(Backup.class); - - private Backup() {} // never - - private static void mkdir(File dir) { - if( !dir.mkdirs() ) - throw new RuntimeException("couldn't make "+dir); - } - - private static void link(File from,File to) throws IOException { - Files.createLink( to.toPath(), from.toPath() ); - } - - private static void backupNonlocal(File from,File to) throws IOException { - mkdir(to); - for( File fromChild : from.listFiles() ) { - File toChild = new File( to, fromChild.getName() ); - if( fromChild.isDirectory() ) { - if( !fromChild.getName().equals("local") ) - backupNonlocal( fromChild, toChild ); - } else if( fromChild.isFile() ) { - link( fromChild, toChild ); - } else { - throw new RuntimeException(fromChild+" isn't dir or file"); - } - } - } - - private static final String getLucenes = - "local Lucene = require 'luan:lucene/Lucene.luan'\n" - +"local Table = require 'luan:Table.luan'\n" - +"return Table.copy(Lucene.instances)\n" - ; - - private static void backupLucene(File from,File to) throws IOException { - if( !new File(from,"site/init.luan").exists() ) { - return; - } - String fromPath = from.getCanonicalPath() + "/"; - LuanTable luceneInstances; - LuanState luan = null; - try { - if( WebHandler.isServing() ) { - luceneInstances = (LuanTable)WebHandler.runLuan( from.getName(), getLucenes, "getLucenes" ); - } else { - luan = new LuanState(); - WebHandler.initLuan( luan, from.toString(), from.getName() ); - PackageLuan.load(luan,"site:/init.luan"); - luceneInstances = (LuanTable)luan.eval(getLucenes); - } - } catch(LuanException e) { - throw new RuntimeException(e); - } - for( Map.Entry entry : luceneInstances.rawIterable() ) { - LuanTable tbl = (LuanTable)entry.getKey(); - LuceneIndex li = (LuceneIndex)tbl.rawGet("java"); - SnapshotDeletionPolicy snapshotDeletionPolicy = li.snapshotDeletionPolicy(); - IndexCommit ic = snapshotDeletionPolicy.snapshot(); - try { - FSDirectory fsdir = (FSDirectory)ic.getDirectory(); - File dir = fsdir.getDirectory(); - String dirPath = dir.toString(); - if( !dirPath.startsWith(fromPath) ) - throw new RuntimeException(fromPath+" "+dirPath); - File toDir = new File( to, dirPath.substring(fromPath.length()) ); - mkdir(toDir); - for( String name : ic.getFileNames() ) { - link( new File(dir,name), new File(toDir,name) ); - } - } finally { - snapshotDeletionPolicy.release(ic); - } - } - if( luan != null ) - luan.close(); - } - - public static void backup(File sitesDir,File backupDir) throws IOException { - mkdir(backupDir); - for( File siteDir : sitesDir.listFiles() ) { - File to = new File( backupDir, siteDir.getName() ); - backupNonlocal( siteDir, to ); - backupLucene( siteDir, to ); - } - } - - public static void main(String[] args) throws Exception { - Log4j.initForConsole(); - backup( new File(args[0]), new File(args[1]) ); - System.exit(0); - } -}
--- a/src/luan/host/jetty/Init.luan Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -local Package = require "luan:Package.luan" -Package.loaded["luan:http/Http.luan"] = require "luan:http/jetty/Http.luan" - -local Luan = require "luan:Luan.luan" -local error = Luan.error -local String = require "luan:String.luan" -local gsub = String.gsub or error() -local Io = require "luan:Io.luan" -local Http = require "luan:http/Http.luan" -local Hosting = require "luan:host/Hosting.luan" -local Mail = require "luan:mail/Mail.luan" - - -local Init = {} - -local dir, domain = ... - -Init.password = Luan.do_file(dir.."/info.luan").password or error() - -Http.dir = "file:"..dir.."/site" - -function Io.schemes.site(path,loading) - return Io.uri( Http.dir..path, loading ) -end - -Hosting.domain = domain -Io.password = Init.password - - --- logging - -java() -local Logger = require "java:org.apache.log4j.Logger" -local Logging = require "luan:logging/Logging.luan" - -local root = gsub(domain,"\.",":") - -Logging.layout = "%d %-5p %c{-1} - %m%n" -Logging.file = dir.."/site/private/local/logs/luan.log" -Logging.max_file_size = "1MB" -local one_mb = 1048576 - -local log_dir = dir.."/site/private/local/logs/" -Logging.appenders = { - [log_dir.."error.log"] = "ERROR" - [log_dir.."warn.log"] = "WARN" - [log_dir.."info.log"] = "INFO" -} - -Logging.log4j_root_logger = Logger.getLogger(root) -Logging.log4j_root_logger.setAdditivity(false) - -local old_log_to_file = Logging.log_to_file - -function Logging.log_to_file(file,logger_name) - Io.schemes.file(file) -- security check - logger_name = logger_name and root .. "." .. logger_name - local appender = old_log_to_file(file,logger_name) - appender.getMaximumFileSize() <= one_mb or error "Logging.max_file_size is too big" - return appender -end - -local old_init = Logging.init - -function Logging.init() - Logging.appenders["System.err"] = nil - Logging.appenders["System.out"] = nil - old_init() -end - -Logging.init() - -local old_logger = Logging.logger - -function Logging.root_logger() - return old_logger(root) -end - -function Logging.logger(name) - return old_logger( root .. "." .. name ) -end - -Init.logger_root = root.."." - - --- mail - fix later - -Hosting.send_mail = Mail.Sender{ - host = "smtpcorp.com"; - username = "smtp@luanhost.com"; -- ? - password = "luanhost"; - port = 2525; -}.send - - -return Init
--- a/src/luan/host/jetty/WebHandler.java Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -package luan.host.jetty; - -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/jetty/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 siteUri = "file:" + 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.equals(siteUri) || name.startsWith(siteUri+"/")) ) - 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"); - } - }; -}
--- a/src/luan/host/jetty/run.luan Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -require "luan:logging/init.luan" -- initialize logging -local Luan = require "luan:Luan.luan" -local error = Luan.error -local do_file = Luan.do_file or error() -local ipairs = Luan.ipairs or error() -local Io = require "luan:Io.luan" -local print = Io.print or error() -local String = require "luan:String.luan" -local Hosting = require "luan:host/Hosting.luan" -local Logging = require "luan:logging/Logging.luan" -local logger = Logging.logger "run" -java() -local WebHandler = require "java:luan.host.jetty.WebHandler" -Hosting.WebHandler = WebHandler - -local here = Io.schemes.file(".").canonical().to_string() -Hosting.sites_dir = here.."/sites/" - --- tmp -local Util = require "classpath:luan/host/Util.luan" -local sites_dir = Io.schemes.file(Hosting.sites_dir) -for _, site in ipairs(sites_dir.children()) do - local password_file = site.child("password") - if password_file.exists() then - local domain = site.name() - local password = password_file.read_text() - Util.write_password(domain,password) - password_file.delete() - logger.info("fixed password for "..domain) - end -end - -do_file "classpath:luan/host/main.luan" - - --- web server - -local Server = require "java:org.eclipse.jetty.server.Server" -local DefaultHandler = require "java:org.eclipse.jetty.server.handler.DefaultHandler" -local HandlerCollection = require "java:org.eclipse.jetty.server.handler.HandlerCollection" -local SessionHandler = require "java:org.eclipse.jetty.server.session.SessionHandler" -local SslSelectChannelConnector = require "java:org.eclipse.jetty.server.ssl.SslSelectChannelConnector" - -local server = Server.new(8080) - -local handlers = HandlerCollection.new() -handlers.setHandlers { - SessionHandler.new(), - WebHandler.new(Hosting.sites_dir,server), - DefaultHandler.new() -} -server.setHandler(handlers); - -server.start() - - ---[[ -local tp = server.getThreadPool() -print(tp) -print(tp.getClass()) -print("max "..tp.getMaxThreads()) -print("getMaxQueued "..tp.getMaxQueued()) - -for _, c in ipairs(server.getConnectors()) do - print(c) - tp = c.getThreadPool() - print(tp) -end - -print "done" -]]
--- a/src/luan/modules/http/jetty/AuthenticationHandler.java Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -package luan.modules.http.jetty; - -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.handler.AbstractHandler; -import org.eclipse.jetty.util.B64Code; - - -public class AuthenticationHandler extends AbstractHandler { - private final String path; - private String password = "password"; - - public AuthenticationHandler(String path) { - this.path = path; - } - - public void setPassword(String password) { - this.password = password; - } - - public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) - throws IOException - { - if( !target.startsWith(path) ) - return; - String pwd = getPassword(request); - if( password.equals(pwd) ) - return; - response.setHeader("WWW-Authenticate","Basic realm=\""+path+"\""); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - baseRequest.setHandled(true); - } - - private static String getPassword(HttpServletRequest request) { - String auth = request.getHeader("Authorization"); - if( auth==null ) - return null; - String[] a = auth.split(" +"); - if( a.length != 2 ) - throw new RuntimeException("auth = "+auth); - if( !a[0].equals("Basic") ) - throw new RuntimeException("auth = "+auth); - auth = new String(B64Code.decode(a[1])); - a = auth.split(":"); - if( a.length != 2 ) - throw new RuntimeException("auth = "+auth); - return a[1]; - } -}
--- a/src/luan/modules/http/jetty/Http.luan Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +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 set_metatable = Luan.set_metatable 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 matches = String.matches or error() -local HttpServicer = require "java:luan.modules.http.jetty.HttpServicer" -local IoLuan = require "java:luan.modules.IoLuan" - - -local Http = {} - -Http.version = "jetty" - -local function sent_error(_,_,_) - error "headers are not accessible after you start writing content" -end - -local sent_error_metatable = { __index=sent_error, __new_index=sent_error } - -function Http.sent_headers(headers) - clear(headers) - set_metatable(headers,sent_error_metatable) -end - - -local function new_common(this) - this = this or {} - this.headers = {} - return this -end - -local function to_list(input) - return type(input) == "table" and input or {input} -end - - -function Http.new_request(this) - this = new_common(this) - this.method = "GET" -- default - -- this.path - -- this.protocol - this.scheme = "http" -- default - this.port = 80 -- default - this.parameters = {} - this.cookies = {} - - function this.query_string() - local string_uri = Io.uri "string:" - local out = string_uri.text_writer() - local and_char = "" - for name, values in pairs(this.parameters) do - for _, value in ipairs(to_list(values)) do - out.write( and_char, url_encode(name), "=", url_encode(value) ) - and_char = "&" - end - end - out.close() - local s = string_uri.read_text() - return s ~= "" and s or nil - end - - function this.full_path() -- compatible with impl - local path = this.path - if this.method ~= "POST" then - local query = this.query_string() - if query ~= nil then - path = path.."?"..query - end - end - return path - end - - function this.url() - return this.scheme.."://"..this.headers["host"]..this.full_path() - end - - return this -end - -local STATUS = { - OK = 200 - MOVED_PERMANENTLY = 301 - -- add more as needed -} -Http.STATUS = STATUS - -function Http.new_response(this) - this = new_common(this) - this.status = STATUS.OK - if this.java ~= nil then - this.send_redirect = this.java.sendRedirect - this.send_error = this.java.sendError - - function this.set_cookie(name,value,attributes) - HttpServicer.setCookie(Http.request.java,this.java,name,value,attributes) - 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.set() - HttpServicer.setResponse(this,this.java) - Http.sent_headers(this.headers) - end - - function this.text_writer() - this.java.setCharacterEncoding "UTF-8" - this.java.setContentType "text/html; charset=UTF-8" - this.set() - return IoLuan.textWriter(this.java.getWriter()) - end - - function this.binary_writer() - this.set() - return IoLuan.binaryWriter(this.java.getOutputStream()) - end - - function this.reset() - this.java.reset() - set_metatable(this.headers,nil) - end - end - return this -end - --- request = new_request{} -- filled in by HttpServicer --- response = new_response{} -- filled in by HttpServicer - - -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/jetty/HttpServicer.java Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,234 +0,0 @@ -package luan.modules.http.jetty; - -import java.io.InputStream; -import java.io.BufferedInputStream; -import java.io.PrintWriter; -import java.io.IOException; -import java.util.Map; -import java.util.Set; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.Enumeration; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import javax.servlet.ServletOutputStream; -import javax.servlet.ServletException; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.Part; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.eclipse.jetty.util.MultiPartInputStream; -import luan.Luan; -import luan.LuanState; -import luan.LuanFunction; -import luan.LuanException; -import luan.LuanTable; -import luan.LuanCloner; -import luan.modules.PackageLuan; -import luan.modules.IoLuan; -import luan.modules.TableLuan; -import luan.modules.Utils; -import luan.modules.url.LuanUrl; - - -public final class HttpServicer { - private static final Logger logger = LoggerFactory.getLogger(HttpServicer.class); - - public static boolean service(LuanState luan,HttpServletRequest request,HttpServletResponse response,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 false; - 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"); - LuanTable requestTbl = (LuanTable)newRequestFn.call(luan); - module.rawPut("request",requestTbl); - requestTbl.rawPut("java",request); - requestTbl.rawPut("method",request.getMethod()); - requestTbl.rawPut("path",request.getRequestURI()); - requestTbl.rawPut("protocol",request.getProtocol()); - requestTbl.rawPut("scheme",request.getScheme()); - requestTbl.rawPut("port",request.getServerPort()); - - LuanTable headersTbl = (LuanTable)requestTbl.rawGet("headers"); - for( Enumeration<String> enKeys = request.getHeaderNames(); enKeys.hasMoreElements(); ) { - String key = enKeys.nextElement(); - List<String> values = new ArrayList<String>(); - for( Enumeration<String> en = request.getHeaders(key); en.hasMoreElements(); ) { - values.add(en.nextElement()); - } - int size = values.size(); - if(size==0) throw new RuntimeException(); - key = key.toLowerCase(); - Object value = size==1 ? values.get(0) : new LuanTable(values); - headersTbl.rawPut(key,value); - } - - LuanTable parametersTbl = (LuanTable)requestTbl.rawGet("parameters"); - String contentType = request.getContentType(); - if( contentType==null || !contentType.startsWith("multipart/form-data") ) { - for( Map.Entry<String,String[]> entry : request.getParameterMap().entrySet() ) { - String[] a = entry.getValue(); - Object value = a.length==1 ? a[0] : new LuanTable(Arrays.asList(a)); - parametersTbl.rawPut(entry.getKey(),value); - } - } else { // multipart - try { - InputStream in = new BufferedInputStream(request.getInputStream()); - final MultiPartInputStream mpis = new MultiPartInputStream(in,contentType,null,null); - mpis.setDeleteOnExit(true); - for( Part p : mpis.getParts() ) { - final MultiPartInputStream.MultiPart part = (MultiPartInputStream.MultiPart)p; - String name = part.getName(); -/* -System.out.println("name = "+name); -System.out.println("getContentType = "+part.getContentType()); -System.out.println("getHeaderNames = "+part.getHeaderNames()); -System.out.println("content-disposition = "+part.getHeader("content-disposition")); -System.out.println(); -*/ - Object value; - String filename = part.getContentDispositionFilename(); - if( filename == null ) { - value = new String(part.getBytes()); - } else { - LuanTable partTbl = new LuanTable(); - partTbl.rawPut("filename",filename); - partTbl.rawPut("content_type",part.getContentType()); - { - InputStream inPart = part.getInputStream(); - byte[] content = Utils.readAll(inPart); - inPart.close(); - partTbl.rawPut("content",content); - } - value = partTbl; - } - Object obj = parametersTbl.rawGet(name); - if( obj == null ) { - parametersTbl.rawPut(name,value); - } else if( obj instanceof LuanTable && ((LuanTable)obj).isList() ) { - LuanTable list = (LuanTable)obj; - list.rawPut(list.rawLength()+1,value); - } else { - LuanTable list = new LuanTable(); - list.rawPut(1,obj); - list.rawPut(2,value); - parametersTbl.rawPut(name,list); - } - } - } catch(IOException e) { - throw new RuntimeException(e); - } catch(ServletException e) { - throw new RuntimeException(e); - } - } - - LuanTable cookieTbl = (LuanTable)requestTbl.rawGet("cookies"); - for( Cookie cookie : request.getCookies() ) { - cookieTbl.rawPut( cookie.getName(), unescape(cookie.getValue()) ); - } - - - // response - LuanTable responseTbl = new LuanTable(); - responseTbl.rawPut("java",response); - LuanFunction newResponseFn = (LuanFunction)module.rawGet("new_response"); - newResponseFn.call( luan, new Object[]{responseTbl} ); - module.rawPut("response",responseTbl); - - fn.call(luan); - return true; - } - - public static void setResponse(LuanTable responseTbl,HttpServletResponse response) throws LuanException { - int status = Luan.asInteger(responseTbl.rawGet("status")); - response.setStatus(status); - LuanTable responseHeaders = (LuanTable)responseTbl.rawGet("headers"); - for( Map.Entry<Object,Object> entry : responseHeaders.rawIterable() ) { - String name = (String)entry.getKey(); - Object val = entry.getValue(); - if( val instanceof LuanTable ) { - LuanTable values = (LuanTable)val; - for( Object value : values.asList() ) { - setResponse(response,name,value); - } - } else { - setResponse(response,name,val); - } - } - } - - private static void setResponse(HttpServletResponse response,String name,Object value) throws LuanException { - if( value instanceof String ) { - response.setHeader(name,(String)value); - return; - } - Integer i = Luan.asInteger(value); - if( i != null ) { - response.setIntHeader(name,i); - return; - } - throw new IllegalArgumentException("value must be string or integer for headers table"); - } - - - - // static utils - - private static String escape(String value) { - return value.replaceAll(";", "%3B"); - } - - private static String unescape(String value) { - return value.replaceAll("%3B", ";"); - } - - private static Cookie getCookie(HttpServletRequest request,String name) { - Cookie[] cookies = request.getCookies(); - if( cookies == null ) - return null; - for (Cookie cookie : cookies) { - if (cookie.getName().equals(name)) - return cookie; - } - return null; - } - - public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,LuanTable attributes) { - Cookie cookie = getCookie(request,name); - if( cookie==null || !cookie.getValue().equals(value) ) { - cookie = new Cookie(name, escape(value)); - if( attributes != null ) { - String path = (String)attributes.rawGet("Path"); - if( path != null ) - cookie.setPath(path); - String domain = (String)attributes.rawGet("Domain"); - if (domain != null && domain.length() > 0) - cookie.setDomain(domain); - String maxAge = (String)attributes.rawGet("Max-Age"); - if( maxAge != null ) - cookie.setMaxAge(Integer.parseInt(maxAge)); - } - response.addCookie(cookie); - } - } - -}
--- a/src/luan/modules/http/jetty/LuanHandler.java Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -package luan.modules.http.jetty; - -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 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.Server; -import org.eclipse.jetty.server.handler.AbstractHandler; -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 extends AbstractHandler { - private final LuanState luanInit; - private final Logger logger; - private String welcomeFile = "index.html"; - 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); - } - } - - @Override public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) - throws IOException - { - if( target.endsWith("/") ) - target += welcomeFile; - Thread thread = Thread.currentThread(); - String oldName = thread.getName(); - thread.setName(request.getHeader("host")+request.getRequestURI()); - lock.readLock().lock(); - try { - if( !HttpServicer.service(luan,request,response,"site:"+target+".luan") ) - return; - } catch(LuanException e) { -//e.printStackTrace(); - String err = e.getLuanStackTraceString(); - logger.error(err); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,err); - } finally { - lock.readLock().unlock(); - thread.setName(oldName); - } - baseRequest.setHandled(true); - } - - public void setWelcomeFile(String welcomeFile) { - this.welcomeFile = welcomeFile; - } - - @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(); - } -/* - @Override public void destroy() { -System.out.println("qqqqqqqqqqqqqqqqqqqq destroy "+this); - super.destroy(); - } -*/ - - 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/jetty/NotFound.java Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package luan.modules.http.jetty; - -import java.io.IOException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.handler.AbstractHandler; - - -public class NotFound extends AbstractHandler { - private final LuanHandler luanHandler; - - public NotFound(LuanHandler luanHandler) { - this.luanHandler = luanHandler; - } - - @Override public void handle(String target,Request baseRequest,HttpServletRequest request,HttpServletResponse response) - throws IOException - { - luanHandler.handle("/not_found",baseRequest,request,response); - } - -}
--- a/src/luan/modules/http/jetty/Server.luan Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +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 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 TimeZone = require "java:java.util.TimeZone" -local JavaServer = require "java:org.eclipse.jetty.server.Server" -local NCSARequestLog = require "java:org.eclipse.jetty.server.NCSARequestLog" -local DefaultHandler = require "java:org.eclipse.jetty.server.handler.DefaultHandler" -local HandlerList = require "java:org.eclipse.jetty.server.handler.HandlerList" -local HandlerCollection = require "java:org.eclipse.jetty.server.handler.HandlerCollection" -local ResourceHandler = require "java:org.eclipse.jetty.server.handler.ResourceHandler" -local RequestLogHandler = require "java:org.eclipse.jetty.server.handler.RequestLogHandler" -local ContextHandler = require "java:org.eclipse.jetty.server.handler.ContextHandler" -local GzipHandler = require "java:org.eclipse.jetty.server.handler.GzipHandler" -local HandlerWrapper = require "java:org.eclipse.jetty.server.handler.HandlerWrapper" -local SessionHandler = require "java:org.eclipse.jetty.server.session.SessionHandler" -local AuthenticationHandler = require "java:luan.modules.http.jetty.AuthenticationHandler" -local LuanHandler = require "java:luan.modules.http.jetty.LuanHandler" -local NotFound = require "java:luan.modules.http.jetty.NotFound" - -local Server = {} - -Server.port = 8080 - -Server.welcome_file = "index.html" - - -Server.luan_handler = LuanHandler.new() - -Server.resource_handler = ResourceHandler.new() -Server.resource_handler.setDirectoriesListed(true) - -Server.handlers = HandlerList.new() -Server.handlers.setHandlers { Server.luan_handler, Server.resource_handler } - -function Server.add_folder(context,dir) - local rh = ResourceHandler.new() - rh.setResourceBase(dir) - rh.setDirectoriesListed(true) - local ch = ContextHandler.new(context) - ch.setHandler(rh) - Server.handlers.addHandler(ch) - return rh -end - -Server.handler_wrapper = HandlerWrapper.new() -Server.handler_wrapper.setHandler(Server.handlers) - -function Server.zip() - local h = GzipHandler.new() - h.setHandler(Server.handler_wrapper.getHandler()) - Server.handler_wrapper.setHandler(h) -end - -Server.log = NCSARequestLog.new() -Server.log.setExtended(false) -Server.log.setLogTimeZone(TimeZone.getDefault().getID()) -Server.log_handler = RequestLogHandler.new() -Server.log_handler.setRequestLog(Server.log) - -function Server.set_log_file(file_name) - Server.log.setFilename(file_name) -end - -local hc = HandlerCollection.new() -hc.setHandlers { SessionHandler.new(), Server.handler_wrapper, DefaultHandler.new(), Server.log_handler } - - -function Server.init(dir) - dir = gsub(dir,"/$","") -- remove trailing '/' if any - Http.dir = dir - function Io.schemes.site(path) - return Io.uri( dir..path ) - end - local base = dir - if matches(base,"^classpath:") then - base = dir.."#"..Server.welcome_file.."#"..Server.welcome_file..".luan" - end - Server.resource_handler.setResourceBase(Io.uri(base).to_string()) - Server.resource_handler.setWelcomeFiles {Server.welcome_file} - Server.luan_handler.setWelcomeFile(Server.welcome_file) - Server.handlers.addHandler(NotFound.new(Server.luan_handler)) - Server.server = JavaServer.new(Server.port) - Server.server.setHandler(hc) -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/jetty/serve.luan Fri Mar 09 15:21:12 2018 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -local Package = require "luan:Package.luan" -Package.loaded["luan:http/Http.luan"] = require "luan:http/jetty/Http.luan" -Package.loaded["luan:http/Server.luan"] = require "luan:http/jetty/Server.luan" - -local Luan = require "luan:Luan.luan" -Luan.load_file("luan:http/serve.luan")(...)