0
|
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 }
|