comparison src/nabble/utils/luan/HttpServicer.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:7ecd1a4ef557
1 package nabble.utils.luan;
2
3 import java.io.InputStream;
4 import java.io.BufferedInputStream;
5 import java.io.PrintWriter;
6 import java.io.IOException;
7 import java.util.Map;
8 import java.util.Set;
9 import java.util.List;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Iterator;
13 import java.util.Enumeration;
14 import java.util.concurrent.Executor;
15 import java.util.concurrent.Executors;
16 import javax.servlet.ServletOutputStream;
17 import javax.servlet.ServletException;
18 import javax.servlet.http.Cookie;
19 import javax.servlet.http.HttpServletRequest;
20 import javax.servlet.http.HttpServletResponse;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23 import luan.Luan;
24 import luan.LuanFunction;
25 import luan.LuanException;
26 import luan.LuanTable;
27 import luan.LuanCloner;
28 import luan.modules.PackageLuan;
29 import luan.modules.IoLuan;
30 import luan.modules.TableLuan;
31 import luan.modules.Utils;
32 import luan.modules.url.LuanUrl;
33
34
35 public final class HttpServicer {
36 private static final Logger logger = LoggerFactory.getLogger(HttpServicer.class);
37
38 private Luan currentLuan;
39
40 public HttpServicer(Luan luan) {
41 this.currentLuan = luan;
42 }
43
44 public boolean service(HttpServletRequest request,HttpServletResponse response,String modName)
45 throws LuanException
46 {
47 LuanFunction fn;
48 Luan luan;
49 synchronized(this) {
50 enableLoad("luan:http/Http.luan",modName);
51 LuanTable module = (LuanTable)PackageLuan.require(currentLuan,"luan:http/Http.luan");
52 Object mod = PackageLuan.load(currentLuan,modName);
53 if( mod.equals(Boolean.FALSE) )
54 return false;
55 if( !(mod instanceof LuanFunction) )
56 throw new LuanException( "module '"+modName+"' must return a function" );
57 LuanCloner cloner = new LuanCloner(LuanCloner.Type.INCREMENTAL);
58 luan = (Luan)cloner.clone(currentLuan);
59 fn = (LuanFunction)cloner.get(mod);
60 }
61
62 LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http.luan");
63
64 // request
65 LuanFunction newRequestFn = (LuanFunction)module.rawGet("new_request");
66 LuanTable requestTbl = (LuanTable)newRequestFn.call();
67 module.rawPut("request",requestTbl);
68 requestTbl.rawPut("java",request);
69 requestTbl.rawPut("method",request.getMethod());
70 requestTbl.rawPut("path",request.getRequestURI());
71 requestTbl.rawPut("protocol",request.getProtocol());
72 requestTbl.rawPut("scheme",request.getScheme());
73 requestTbl.rawPut("port",request.getServerPort());
74
75 LuanTable headersTbl = (LuanTable)requestTbl.rawGet("headers");
76 for( Enumeration<String> enKeys = request.getHeaderNames(); enKeys.hasMoreElements(); ) {
77 String key = enKeys.nextElement();
78 List<String> values = new ArrayList<String>();
79 for( Enumeration<String> en = request.getHeaders(key); en.hasMoreElements(); ) {
80 values.add(en.nextElement());
81 }
82 int size = values.size();
83 if(size==0) throw new RuntimeException();
84 key = key.toLowerCase();
85 Object value = size==1 ? values.get(0) : new LuanTable(luan,values);
86 headersTbl.rawPut(key,value);
87 }
88
89 LuanTable parametersTbl = (LuanTable)requestTbl.rawGet("parameters");
90 for( Object obj : request.getParameterMap().entrySet() ) {
91 Map.Entry entry = (Map.Entry)obj;
92 String[] a = (String[])entry.getValue();
93 Object value = a.length==1 ? a[0] : new LuanTable(luan,Arrays.asList(a));
94 parametersTbl.rawPut(entry.getKey(),value);
95 }
96 LuanTable cookieTbl = (LuanTable)requestTbl.rawGet("cookies");
97 for( Cookie cookie : request.getCookies() ) {
98 cookieTbl.rawPut( cookie.getName(), unescape(cookie.getValue()) );
99 }
100
101
102 // response
103 LuanTable responseTbl = new LuanTable(luan);
104 responseTbl.rawPut("java",response);
105 LuanFunction newResponseFn = (LuanFunction)module.rawGet("new_response");
106 newResponseFn.call( responseTbl );
107 module.rawPut("response",responseTbl);
108
109 fn.call();
110 return true;
111 }
112
113 public static void setResponse(LuanTable responseTbl,HttpServletResponse response) throws LuanException {
114 int status = Luan.asInteger(responseTbl.rawGet("status"));
115 response.setStatus(status);
116 LuanTable responseHeaders = (LuanTable)responseTbl.rawGet("headers");
117 for( Map.Entry<Object,Object> entry : responseHeaders.rawIterable() ) {
118 String name = (String)entry.getKey();
119 Object val = entry.getValue();
120 if( val instanceof LuanTable ) {
121 LuanTable values = (LuanTable)val;
122 for( Object value : values.asList() ) {
123 setResponse(response,name,value);
124 }
125 } else {
126 setResponse(response,name,val);
127 }
128 }
129 }
130
131 private static void setResponse(HttpServletResponse response,String name,Object value) throws LuanException {
132 if( value instanceof String ) {
133 response.setHeader(name,(String)value);
134 return;
135 }
136 Integer i = Luan.asInteger(value);
137 if( i != null ) {
138 response.setIntHeader(name,i);
139 return;
140 }
141 throw new IllegalArgumentException("value must be string or integer for headers table");
142 }
143
144 private void enableLoad(String... mods) throws LuanException {
145 LuanTable loaded = PackageLuan.loaded(currentLuan);
146 for( String mod : mods ) {
147 if( loaded.rawGet(mod) == null ) {
148 LuanCloner cloner = new LuanCloner(LuanCloner.Type.COMPLETE);
149 currentLuan = (Luan)cloner.clone(currentLuan);
150 break;
151 }
152 }
153 }
154
155
156
157 // static utils
158
159 private static String escape(String value) {
160 return value.replaceAll(";", "%3B");
161 }
162
163 private static String unescape(String value) {
164 return value.replaceAll("%3B", ";");
165 }
166
167 private static Cookie getCookie(HttpServletRequest request,String name) {
168 Cookie[] cookies = request.getCookies();
169 if( cookies == null )
170 return null;
171 for (Cookie cookie : cookies) {
172 if (cookie.getName().equals(name))
173 return cookie;
174 }
175 return null;
176 }
177
178 public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,LuanTable attributes) {
179 Cookie cookie = getCookie(request,name);
180 if( cookie==null || !cookie.getValue().equals(value) ) {
181 cookie = new Cookie(name, escape(value));
182 if( attributes != null ) {
183 String path = (String)attributes.rawGet("Path");
184 if( path != null )
185 cookie.setPath(path);
186 String domain = (String)attributes.rawGet("Domain");
187 if (domain != null && domain.length() > 0)
188 cookie.setDomain(domain);
189 String maxAge = (String)attributes.rawGet("Max-Age");
190 if( maxAge != null )
191 cookie.setMaxAge(Integer.parseInt(maxAge));
192 }
193 response.addCookie(cookie);
194 }
195 }
196
197 }