Mercurial Hosting > luan
comparison http/src/luan/modules/http/HttpServicer.java @ 497:55f9f74f1e55
Http.request is now pure luan
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 17 May 2015 19:25:47 -0600 |
parents | c65df5b25932 |
children | ee55be414a34 |
comparison
equal
deleted
inserted
replaced
496:c65df5b25932 | 497:55f9f74f1e55 |
---|---|
72 fn = (LuanFunction)cloner.get(fn); | 72 fn = (LuanFunction)cloner.get(fn); |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
76 LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http"); | 76 LuanTable module = (LuanTable)PackageLuan.require(luan,"luan:http/Http"); |
77 HttpServicer lib = new HttpServicer(request,response); | 77 |
78 try { | 78 // request |
79 module.put( luan, "request", lib.requestTable() ); | 79 LuanTable requestTbl = (LuanTable)luan.call( (LuanFunction)module.rawGet("new_request") ); |
80 module.put( luan, "response", lib.responseTable() ); | 80 module.rawPut("request",requestTbl); |
81 } catch(NoSuchMethodException e) { | 81 requestTbl.rawPut("java",request); |
82 throw new RuntimeException(e); | 82 requestTbl.rawPut("method",request.getMethod()); |
83 } | 83 requestTbl.rawPut("path",request.getRequestURI()); |
84 | 84 requestTbl.rawPut("protocol",request.getProtocol()); |
85 luan.call(fn,"<http>"); | 85 requestTbl.rawPut("scheme",request.getScheme()); |
86 return true; | 86 |
87 } | 87 LuanTable headersTbl = (LuanTable)requestTbl.rawGet("headers"); |
88 | 88 for( Enumeration<String> enKeys = request.getHeaderNames(); enKeys.hasMoreElements(); ) { |
89 private static LuanFunction getService(LuanState luan,LuanTable tbl) | 89 String key = enKeys.nextElement(); |
90 throws LuanException | 90 key = key.toLowerCase().replace('-','_'); |
91 { | 91 LuanTable values = new LuanTable(); |
92 Object respond = tbl.get(luan,"respond"); | 92 for( Enumeration<String> en = request.getHeaders(key); en.hasMoreElements(); ) { |
93 if( respond == null ) | 93 values.rawPut(values.rawLength()+1,en.nextElement()); |
94 throw luan.exception( "function 'respond' is not defined" ); | 94 } |
95 if( !(respond instanceof LuanFunction) ) | 95 headersTbl.rawPut(key,values); |
96 throw luan.exception( "'respond' must be a function but is a " + Luan.type(respond) ); | 96 } |
97 return (LuanFunction)respond; | 97 |
98 } | 98 LuanTable parametersTbl = (LuanTable)requestTbl.rawGet("parameters"); |
99 | |
100 | |
101 private final HttpServletRequest request; | |
102 private final HttpServletResponse response; | |
103 // private PrintWriter writer = null; | |
104 // private ServletOutputStream sos = null; | |
105 | |
106 private HttpServicer(HttpServletRequest request,HttpServletResponse response) { | |
107 this.request = request; | |
108 this.response = response; | |
109 } | |
110 | |
111 private LuanTable requestTable() throws NoSuchMethodException { | |
112 LuanTable tbl = LuanPropertyMeta.INSTANCE.newTable(); | |
113 LuanTable getters = LuanPropertyMeta.INSTANCE.getters(tbl); | |
114 tbl.rawPut("java",request); | |
115 LuanTable parameters = new NameMeta() { | |
116 | |
117 @Override Object get(String name) { | |
118 return request.getParameter(name); | |
119 } | |
120 | |
121 @Override protected Iterator keys(LuanTable tbl) { | |
122 return new EnumerationIterator(request.getParameterNames()); | |
123 } | |
124 | |
125 @Override protected String type(LuanTable tbl) { | |
126 return "request.parameters"; | |
127 } | |
128 | |
129 }.newTable(); | |
130 tbl.rawPut( "parameters", parameters ); | |
131 add( tbl, "get_parameter_values", String.class ); | |
132 LuanTable headers = new NameMeta() { | |
133 | |
134 @Override Object get(String name) { | |
135 return request.getHeader(name); | |
136 } | |
137 | |
138 @Override protected Iterator keys(LuanTable tbl) { | |
139 return new EnumerationIterator(request.getHeaderNames()); | |
140 } | |
141 | |
142 @Override protected String type(LuanTable tbl) { | |
143 return "request.headers"; | |
144 } | |
145 | |
146 }.newTable(); | |
147 tbl.rawPut( "headers", headers ); | |
148 getters.rawPut( "method", new LuanJavaFunction( | |
149 HttpServletRequest.class.getMethod( "getMethod" ), request | |
150 ) ); | |
151 getters.rawPut( "path", new LuanJavaFunction( | |
152 HttpServletRequest.class.getMethod( "getRequestURI" ), request | |
153 ) ); | |
154 getters.rawPut( "server_name", new LuanJavaFunction( | |
155 HttpServletRequest.class.getMethod( "getServerName" ), request | |
156 ) ); | |
157 getters.rawPut( "url", new LuanJavaFunction( | |
158 HttpServicer.class.getMethod( "getURL" ), this | |
159 ) ); | |
160 getters.rawPut( "query_string", new LuanJavaFunction( | |
161 HttpServicer.class.getMethod( "getQueryString" ), this | |
162 ) ); | |
163 getters.rawPut( "remote_address", new LuanJavaFunction( | |
164 HttpServletRequest.class.getMethod( "getRemoteAddr" ), request | |
165 ) ); | |
166 getters.rawPut( "protocol", new LuanJavaFunction( | |
167 HttpServletRequest.class.getMethod( "getProtocol" ), request | |
168 ) ); | |
169 getters.rawPut( "scheme", new LuanJavaFunction( | |
170 HttpServletRequest.class.getMethod( "getScheme" ), request | |
171 ) ); | |
172 getters.rawPut( "is_secure", new LuanJavaFunction( | |
173 HttpServletRequest.class.getMethod( "isSecure" ), request | |
174 ) ); | |
175 LuanTable cookies = new LuanMeta() { | |
176 | |
177 @Override public Object __index(LuanState luan,LuanTable tbl,Object key) { | |
178 if( !(key instanceof String) ) | |
179 return null; | |
180 String name = (String)key; | |
181 return getCookieValue(request,name); | |
182 } | |
183 | |
184 @Override protected Iterator<Object> keys(LuanTable tbl) { | |
185 return new Iterator<Object>() { | |
186 final Cookie[] cookies = request.getCookies(); | |
187 int i = 0; | |
188 | |
189 @Override public boolean hasNext() { | |
190 return i < cookies.length; | |
191 } | |
192 @Override public Object next() { | |
193 return cookies[i++].getName(); | |
194 } | |
195 @Override public void remove() { | |
196 throw new UnsupportedOperationException(); | |
197 } | |
198 }; | |
199 } | |
200 | |
201 @Override protected String type(LuanTable tbl) { | |
202 return "request.cookies"; | |
203 } | |
204 | |
205 }.newTable(); | |
206 tbl.rawPut( "cookies", cookies ); | |
207 | |
208 String contentType = request.getContentType(); | 99 String contentType = request.getContentType(); |
209 if( contentType!=null && contentType.startsWith("multipart/form-data") ) { | 100 if( contentType==null || !contentType.startsWith("multipart/form-data") ) { |
101 for( Map.Entry<String,String[]> entry : request.getParameterMap().entrySet() ) { | |
102 parametersTbl.rawPut(entry.getKey(),new LuanTable(Arrays.asList(entry.getValue()))); | |
103 } | |
104 } else { // multipart | |
210 try { | 105 try { |
211 InputStream in = new BufferedInputStream(request.getInputStream()); | 106 InputStream in = new BufferedInputStream(request.getInputStream()); |
212 final MultiPartInputStream mpis = new MultiPartInputStream(in,contentType,null,null); | 107 final MultiPartInputStream mpis = new MultiPartInputStream(in,contentType,null,null); |
213 mpis.setDeleteOnExit(true); | 108 mpis.setDeleteOnExit(true); |
214 parameters = new LuanTable(); | |
215 final Map map = new HashMap(); | |
216 for( Part p : mpis.getParts() ) { | 109 for( Part p : mpis.getParts() ) { |
217 final MultiPartInputStream.MultiPart part = (MultiPartInputStream.MultiPart)p; | 110 final MultiPartInputStream.MultiPart part = (MultiPartInputStream.MultiPart)p; |
218 String name = part.getName(); | 111 String name = part.getName(); |
219 Object value; | 112 Object value; |
220 String filename = part.getContentDispositionFilename(); | 113 String filename = part.getContentDispositionFilename(); |
236 } | 129 } |
237 } | 130 } |
238 } ); | 131 } ); |
239 value = partTbl; | 132 value = partTbl; |
240 } | 133 } |
241 parameters.rawPut(name,value); | 134 LuanTable list = (LuanTable)parametersTbl.rawGet(name); |
242 Object old = map.get(name); | 135 if( list == null ) { |
243 if( old == null ) { | 136 list = new LuanTable(); |
244 map.put(name,value); | 137 parametersTbl.rawPut(name,list); |
245 } else if( old instanceof Object[] ) { | |
246 Object[] aOld = (Object[])old; | |
247 Object[] aNew = new Object[aOld.length+1]; | |
248 System.arraycopy(aOld,0,aNew,0,aOld.length); | |
249 aNew[aOld.length] = value; | |
250 map.put(name,aNew); | |
251 } else { | |
252 map.put(name,new Object[]{old,value}); | |
253 } | 138 } |
139 parametersTbl.rawPut(parametersTbl.rawLength()+1,value); | |
254 } | 140 } |
255 tbl.rawPut( "parameters", parameters ); | |
256 tbl.rawPut( "get_parameter_values", new LuanFunction() { | |
257 @Override public Object call(LuanState luan,Object[] args) throws LuanException { | |
258 return args.length==0 ? null : map.get(args[0]); | |
259 } | |
260 } ); | |
261 } catch(IOException e) { | 141 } catch(IOException e) { |
262 throw new RuntimeException(e); | 142 throw new RuntimeException(e); |
263 } catch(ServletException e) { | 143 } catch(ServletException e) { |
264 throw new RuntimeException(e); | 144 throw new RuntimeException(e); |
265 } | 145 } |
266 } | 146 } |
267 | 147 |
268 return tbl; | 148 LuanTable cookieTbl = (LuanTable)requestTbl.rawGet("cookie"); |
149 for( Cookie cookie : request.getCookies() ) { | |
150 cookieTbl.rawPut( cookie.getName(), unescape(cookie.getValue()) ); | |
151 } | |
152 | |
153 HttpServicer lib = new HttpServicer(request,response); | |
154 try { | |
155 module.put( luan, "response", lib.responseTable() ); | |
156 } catch(NoSuchMethodException e) { | |
157 throw new RuntimeException(e); | |
158 } | |
159 | |
160 luan.call(fn,"<http>"); | |
161 return true; | |
162 } | |
163 | |
164 private static LuanFunction getService(LuanState luan,LuanTable tbl) | |
165 throws LuanException | |
166 { | |
167 Object respond = tbl.get(luan,"respond"); | |
168 if( respond == null ) | |
169 throw luan.exception( "function 'respond' is not defined" ); | |
170 if( !(respond instanceof LuanFunction) ) | |
171 throw luan.exception( "'respond' must be a function but is a " + Luan.type(respond) ); | |
172 return (LuanFunction)respond; | |
173 } | |
174 | |
175 | |
176 private final HttpServletRequest request; | |
177 private final HttpServletResponse response; | |
178 | |
179 private HttpServicer(HttpServletRequest request,HttpServletResponse response) { | |
180 this.request = request; | |
181 this.response = response; | |
269 } | 182 } |
270 | 183 |
271 private LuanTable responseTable() throws NoSuchMethodException { | 184 private LuanTable responseTable() throws NoSuchMethodException { |
272 LuanTable tbl = LuanPropertyMeta.INSTANCE.newTable(); | 185 LuanTable tbl = LuanPropertyMeta.INSTANCE.newTable(); |
273 LuanTable getters = LuanPropertyMeta.INSTANCE.getters(tbl); | 186 LuanTable getters = LuanPropertyMeta.INSTANCE.getters(tbl); |
344 } | 257 } |
345 | 258 |
346 private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { | 259 private void add(LuanTable t,String method,Class<?>... parameterTypes) throws NoSuchMethodException { |
347 t.rawPut( method, new LuanJavaFunction(HttpServicer.class.getMethod(method,parameterTypes),this) ); | 260 t.rawPut( method, new LuanJavaFunction(HttpServicer.class.getMethod(method,parameterTypes),this) ); |
348 } | 261 } |
349 /* | 262 |
350 public void text_write(LuanState luan,Object... args) throws LuanException, IOException { | |
351 if( writer == null ) | |
352 writer = response.getWriter(); | |
353 for( Object obj : args ) { | |
354 writer.print( luan.toString(obj) ); | |
355 } | |
356 } | |
357 */ | |
358 public LuanTable text_writer() throws IOException { | 263 public LuanTable text_writer() throws IOException { |
359 return IoLuan.textWriter(response.getWriter()); | 264 return IoLuan.textWriter(response.getWriter()); |
360 } | 265 } |
361 | 266 |
362 public Object[] get_parameter_values(String name) { | |
363 return request.getParameterValues(name); | |
364 } | |
365 | |
366 public void set_cookie(String name,String value,boolean isPersistent, String domain) { | 267 public void set_cookie(String name,String value,boolean isPersistent, String domain) { |
367 setCookie(request,response,name,value,isPersistent,domain); | 268 setCookie(request,response,name,value,isPersistent,domain); |
368 } | 269 } |
369 | 270 |
370 public void remove_cookie(String name, String domain) { | 271 public void remove_cookie(String name, String domain) { |
371 removeCookie(request,response,name,domain); | 272 removeCookie(request,response,name,domain); |
372 } | 273 } |
373 | 274 |
374 | 275 |
375 // static utils | 276 // static utils |
376 | |
377 public String getQueryString() { | |
378 return getQueryString(request); | |
379 } | |
380 | |
381 public static String getQueryString(HttpServletRequest request) { | |
382 return getQueryString(request,0); | |
383 } | |
384 | |
385 public static String getQueryString(HttpServletRequest request,int maxValueLen) { | |
386 String method = request.getMethod(); | |
387 if( method.equals("GET") ) | |
388 return request.getQueryString(); | |
389 if( !method.equals("POST") && !method.equals("HEAD") ) | |
390 throw new RuntimeException(method); | |
391 Enumeration en = request.getParameterNames(); | |
392 StringBuilder queryBuf = new StringBuilder(); | |
393 if( !en.hasMoreElements() ) | |
394 return null; | |
395 do { | |
396 String param = (String)en.nextElement(); | |
397 String value = request.getParameter(param); | |
398 if( maxValueLen > 0 ) { | |
399 int len = value.length(); | |
400 if( len > maxValueLen ) | |
401 value = value.substring(0,maxValueLen) + "..." + (len-maxValueLen); | |
402 } | |
403 queryBuf.append(param); | |
404 queryBuf.append('='); | |
405 queryBuf.append(value); | |
406 queryBuf.append('&'); | |
407 } while( en.hasMoreElements() ); | |
408 queryBuf.deleteCharAt(queryBuf.length() - 1); | |
409 return queryBuf.toString(); | |
410 } | |
411 | |
412 public String getURL() { | |
413 return getURL(request); | |
414 } | |
415 | |
416 public static String getURL(HttpServletRequest request) { | |
417 return getURL(request,0); | |
418 } | |
419 | |
420 public static String getURL(HttpServletRequest request,int maxValueLen) { | |
421 // StringBuffer buf = HttpUtils.getRequestURL(request); | |
422 StringBuffer buf = request.getRequestURL(); | |
423 String qStr = getQueryString(request,maxValueLen); | |
424 if(qStr != null && qStr.length() > 0) { | |
425 buf.append('?'); | |
426 buf.append(qStr); | |
427 } | |
428 return buf.toString(); | |
429 } | |
430 | 277 |
431 private static String escape(String value) { | 278 private static String escape(String value) { |
432 return value.replaceAll(";", "%3B"); | 279 return value.replaceAll(";", "%3B"); |
433 } | 280 } |
434 | 281 |
443 for (Cookie cookie : cookies) { | 290 for (Cookie cookie : cookies) { |
444 if (cookie.getName().equals(name)) | 291 if (cookie.getName().equals(name)) |
445 return cookie; | 292 return cookie; |
446 } | 293 } |
447 return null; | 294 return null; |
448 } | |
449 | |
450 public static String getCookieValue(HttpServletRequest request,String name) { | |
451 Cookie cookie = getCookie(request,name); | |
452 return cookie==null ? null : unescape(cookie.getValue()); | |
453 } | 295 } |
454 | 296 |
455 public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,boolean isPersistent, String domain) { | 297 public static void setCookie(HttpServletRequest request,HttpServletResponse response,String name,String value,boolean isPersistent, String domain) { |
456 Cookie cookie = getCookie(request,name); | 298 Cookie cookie = getCookie(request,name); |
457 if( cookie==null || !cookie.getValue().equals(value) ) { | 299 if( cookie==null || !cookie.getValue().equals(value) ) { |
483 | 325 |
484 | 326 |
485 | 327 |
486 // util classes | 328 // util classes |
487 | 329 |
488 static final class EnumerationIterator implements Iterator { | |
489 private final Enumeration en; | |
490 | |
491 EnumerationIterator(Enumeration en) { | |
492 this.en = en; | |
493 } | |
494 | |
495 @Override public boolean hasNext() { | |
496 return en.hasMoreElements(); | |
497 } | |
498 | |
499 @Override public Object next() { | |
500 return en.nextElement(); | |
501 } | |
502 | |
503 @Override public void remove() { | |
504 throw new UnsupportedOperationException(); | |
505 } | |
506 } | |
507 | |
508 private static abstract class NameMeta extends LuanMeta { | 330 private static abstract class NameMeta extends LuanMeta { |
509 abstract Object get(String name); | 331 abstract Object get(String name); |
510 | 332 |
511 @Override public Object __index(LuanState luan,LuanTable tbl,Object key) { | 333 @Override public Object __index(LuanState luan,LuanTable tbl,Object key) { |
512 if( !(key instanceof String) ) | 334 if( !(key instanceof String) ) |
515 return get(name); | 337 return get(name); |
516 } | 338 } |
517 | 339 |
518 }; | 340 }; |
519 | 341 |
520 private static String string(Object value) { | |
521 if( !(value instanceof String) ) | |
522 throw new IllegalArgumentException("value must be string"); | |
523 return (String)value; | |
524 } | |
525 } | 342 } |