Mercurial Hosting > luan
view http/src/luan/modules/http/HttpServicer.java @ 509:e3b0846dc2ef
throw exception for invalid indexes of string, binary, or java
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 22 May 2015 02:02:49 -0600 |
parents | 7bc63886d4f2 |
children | 7d1afc73f835 |
line wrap: on
line source
package luan.modules.http; import java.io.InputStream; import java.io.BufferedInputStream; import java.io.PrintWriter; import java.io.IOException; import java.util.Map; import java.util.HashMap; import java.util.AbstractMap; 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 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.HttpSession; 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.LuanElement; import luan.LuanException; import luan.LuanTable; import luan.LuanMeta; import luan.LuanJavaFunction; import luan.LuanPropertyMeta; import luan.DeepCloner; import luan.modules.PackageLuan; import luan.modules.IoLuan; import luan.modules.TableLuan; import luan.modules.Utils; 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) { LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http"); LuanTable per_session_pages = (LuanTable)module.rawGet("per_session_pages"); Object mod = PackageLuan.load(luan,modName); if( mod==null ) return false; if( !(mod instanceof LuanFunction) ) throw luan.exception( "module '"+modName+"' must return a function" ); if( Boolean.TRUE.equals(per_session_pages.rawGet(mod)) ) { HttpSession session = request.getSession(); LuanState sessionLuan = (LuanState)session.getValue("luan"); if( sessionLuan!=null ) { luan = sessionLuan; } else { DeepCloner cloner = new DeepCloner(); luan = (LuanState)cloner.deepClone(luan); session.putValue("luan",luan); } fn = (LuanFunction)PackageLuan.require(luan,modName); } else { DeepCloner cloner = new DeepCloner(); luan = (LuanState)cloner.deepClone(luan); fn = (LuanFunction)cloner.get(mod); } } LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http"); // request LuanTable requestTbl = (LuanTable)luan.call( (LuanFunction)module.rawGet("new_request") ); 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()); LuanTable headersTbl = (LuanTable)requestTbl.rawGet("headers"); for( Enumeration<String> enKeys = request.getHeaderNames(); enKeys.hasMoreElements(); ) { String key = enKeys.nextElement(); LuanTable values = new LuanTable(); for( Enumeration<String> en = request.getHeaders(key); en.hasMoreElements(); ) { values.rawPut(values.rawLength()+1,en.nextElement()); } key = toLuanHeaderName(key); headersTbl.rawPut(key,values); } 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() ) { parametersTbl.rawPut(entry.getKey(),new LuanTable(Arrays.asList(entry.getValue()))); } } 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(); Object value; String filename = part.getContentDispositionFilename(); if( filename == null ) { value = new String(part.getBytes()); } else { LuanTable partTbl = LuanPropertyMeta.INSTANCE.newTable(); partTbl.rawPut("filename",filename); partTbl.rawPut("content_type",part.getContentType()); LuanPropertyMeta.INSTANCE.getters(partTbl).rawPut( "content", new LuanFunction() { @Override public Object call(LuanState luan,Object[] args) throws LuanException { try { InputStream in = part.getInputStream(); byte[] content = Utils.readAll(in); in.close(); return content; } catch(IOException e) { throw new RuntimeException(e); } } } ); value = partTbl; } LuanTable list = (LuanTable)parametersTbl.rawGet(name); if( list == null ) { list = new LuanTable(); parametersTbl.rawPut(name,list); } parametersTbl.rawPut(parametersTbl.rawLength()+1,value); } } catch(IOException e) { throw new RuntimeException(e); } catch(ServletException e) { throw new RuntimeException(e); } } LuanTable cookieTbl = (LuanTable)requestTbl.rawGet("cookie"); for( Cookie cookie : request.getCookies() ) { cookieTbl.rawPut( cookie.getName(), unescape(cookie.getValue()) ); } // response LuanTable responseTbl = new LuanTable(); responseTbl.rawPut("java",response); luan.call( (LuanFunction)module.rawGet("new_response"), new Object[]{responseTbl} ); module.rawPut("response",responseTbl); luan.call(fn,"<http>"); setResponse(module,response); return true; } private static void setResponse(LuanTable module,HttpServletResponse response) throws LuanException { LuanTable responseTbl = (LuanTable)module.rawGet("response"); 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(); name = toHttpHeaderName(name); LuanTable values = (LuanTable)entry.getValue(); for( Object value : values.asList() ) { if( value instanceof String ) { response.setHeader(name,(String)value); continue; } Integer i = Luan.asInteger(value); if( i != null ) { response.setIntHeader(name,i); continue; } throw new IllegalArgumentException("value must be string or integer for headers table"); } } // no more headers responseTbl.rawPut("headers",null); responseTbl.rawPut("header",null); } // static utils public static String toLuanHeaderName(String httpName) { return httpName.toLowerCase().replace('-','_'); } public static String toHttpHeaderName(String luanName) { StringBuilder buf = new StringBuilder(); boolean capitalize = true; char[] a = luanName.toCharArray(); for( int i=0; i<a.length; i++ ) { char c = a[i]; if( c == '_' ) { a[i] = '-'; capitalize = true; } else if( capitalize ) { a[i] = Character.toUpperCase(c); capitalize = false; } } return String.valueOf(a); } 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,boolean isPersistent, String domain) { Cookie cookie = getCookie(request,name); if( cookie==null || !cookie.getValue().equals(value) ) { cookie = new Cookie(name, escape(value)); cookie.setPath("/"); if (domain != null && domain.length() > 0) cookie.setDomain(domain); if( isPersistent ) cookie.setMaxAge(10000000); response.addCookie(cookie); } } public static void removeCookie(HttpServletRequest request, HttpServletResponse response, String name, String domain ) { Cookie cookie = getCookie(request, name); if(cookie != null) { Cookie delCookie = new Cookie(name, "delete"); delCookie.setPath("/"); delCookie.setMaxAge(0); if (domain != null && domain.length() > 0) delCookie.setDomain(domain); response.addCookie(delCookie); } } }