Mercurial Hosting > luan
view src/luan/modules/http/jetty/HttpServicer.java @ 1159:3ef883468fd0
remove Http.per_session_pages
fix clone closure bug
replace Thread.global with Thread.global_callable()
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 05 Feb 2018 12:37:59 -0700 |
parents | bbad9a21277c |
children |
line wrap: on
line source
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); } } }