Mercurial Hosting > nabble
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 } |