Mercurial Hosting > luan
annotate src/luan/host/WebHandler.java @ 1810:3c43b07e12b7 default tip
minor
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 12 May 2024 22:00:42 -0600 |
parents | 9157e0d5936e |
children |
rev | line source |
---|---|
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
1 package luan.host; |
1135 | 2 |
1766 | 3 import java.io.Closeable; |
1135 | 4 import java.io.File; |
1501 | 5 import java.io.IOException; |
1766 | 6 import java.lang.ref.Reference; |
7 import java.lang.ref.WeakReference; | |
8 import java.lang.reflect.Method; | |
9 import java.util.Set; | |
10 import java.util.Collections; | |
11 import java.util.concurrent.ConcurrentHashMap; | |
1402
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1400
diff
changeset
|
12 import goodjava.logging.Logger; |
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1400
diff
changeset
|
13 import goodjava.logging.LoggerFactory; |
1501 | 14 import goodjava.io.IoUtils; |
1402
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1400
diff
changeset
|
15 import goodjava.webserver.Handler; |
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1400
diff
changeset
|
16 import goodjava.webserver.Request; |
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1400
diff
changeset
|
17 import goodjava.webserver.Response; |
27efb1fcbcb5
move luan.lib to goodjava
Franklin Schmidt <fschmidt@gmail.com>
parents:
1400
diff
changeset
|
18 import goodjava.webserver.handlers.DomainHandler; |
1598 | 19 import goodjava.webserver.handlers.IndexHandler; |
20 import goodjava.webserver.handlers.ListHandler; | |
21 import goodjava.webserver.handlers.ContentTypeHandler; | |
22 import goodjava.webserver.handlers.SafeHandler; | |
23 import goodjava.webserver.handlers.LogHandler; | |
1602
55d7b60c074d
add DirHandler to WebHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1600
diff
changeset
|
24 import goodjava.webserver.handlers.FileHandler; |
55d7b60c074d
add DirHandler to WebHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1600
diff
changeset
|
25 import goodjava.webserver.handlers.DirHandler; |
1607 | 26 import goodjava.webserver.handlers.HeadersHandler; |
1608
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
27 import goodjava.webserver.handlers.BasicAuthHandler; |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
28 import goodjava.webserver.handlers.RegexHandler; |
1330 | 29 import luan.Luan; |
1135 | 30 import luan.LuanException; |
31 import luan.LuanTable; | |
1330 | 32 import luan.LuanFunction; |
1766 | 33 import luan.LuanJavaFunction; |
1330 | 34 import luan.LuanClosure; |
1335 | 35 import luan.LuanRuntimeException; |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
36 import luan.modules.http.LuanHandler; |
1598 | 37 import luan.modules.http.NotFound; |
1454 | 38 import luan.modules.logging.LuanLogger; |
1135 | 39 |
40 | |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
41 public class WebHandler implements Handler { |
1135 | 42 private static final Logger logger = LoggerFactory.getLogger(WebHandler.class); |
1600
8a717f0b7f45
add DailyRollingFileAppender.deleteAfter
Franklin Schmidt <fschmidt@gmail.com>
parents:
1599
diff
changeset
|
43 private static final long days30 = 1000L*60*60*24*30; |
1135 | 44 |
1766 | 45 private static final class MyHandler implements Handler, Closeable { |
1598 | 46 private final Handler handler; |
47 final LuanHandler luanHandler; | |
48 | |
49 MyHandler(Handler handler,LuanHandler luanHandler) { | |
50 this.handler = handler; | |
51 this.luanHandler = luanHandler; | |
52 } | |
53 | |
54 @Override public Response handle(Request request) { | |
55 return handler.handle(request); | |
56 } | |
1766 | 57 |
58 @Override public void close() { | |
1767 | 59 dontGc.remove(this); |
1766 | 60 luanHandler.close(); |
61 } | |
1767 | 62 |
63 protected void finalize() throws Throwable { | |
64 // logger.info("gc "+luanHandler.domain); | |
65 close(); | |
66 } | |
1598 | 67 } |
68 | |
1315 | 69 private static final DomainHandler.Factory factory = new DomainHandler.Factory() { |
70 public Handler newHandler(String domain) { | |
71 File dir = new File(sitesDir,domain); | |
1400
221eedb0f54e
fix inner class gc bug
Franklin Schmidt <fschmidt@gmail.com>
parents:
1392
diff
changeset
|
72 if( !dir.exists() ) |
1315 | 73 return null; |
74 String dirStr = dir.toString(); | |
1230 | 75 |
1315 | 76 String logDir = dirStr + "/site/private/local/logs/web"; |
1501 | 77 try { |
78 IoUtils.mkdirs(new File(logDir)); | |
79 } catch(IOException e) { | |
80 throw new RuntimeException(e); | |
81 } | |
1230 | 82 |
1333
25746915a241
merge Luan and LuanState
Franklin Schmidt <fschmidt@gmail.com>
parents:
1332
diff
changeset
|
83 Luan luan = new Luan(); |
1608
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
84 String password; |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
85 LuanLogger.startThreadLogging(luan); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
86 try { |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
87 LuanFunction fn = Luan.loadClasspath(luan,"luan/host/init.luan"); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
88 fn.call(luan,dirStr,domain); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
89 LuanTable Io = (LuanTable)luan.require("luan:Io.luan"); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
90 password = (String)Io.get(luan,"password"); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
91 if( password==null ) throw new NullPointerException(); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
92 } catch(LuanException e) { |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
93 throw new LuanRuntimeException(e); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
94 } finally { |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
95 LuanLogger.endThreadLogging(); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
96 } |
1766 | 97 Fns fns = new Fns(); |
98 try { | |
99 LuanTable Http = (LuanTable)luan.require("luan:http/Http.luan"); | |
100 Http.put( luan, "dont_gc", new LuanJavaFunction(dontGcMethod,fns) ); | |
101 } catch(LuanException e) { | |
102 throw new RuntimeException(e); | |
103 } | |
1608
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
104 security(luan,dirStr); |
1598 | 105 LuanHandler luanHandler = new LuanHandler(luan,domain); |
106 | |
1605
ef9d96aeb541
use FileHandler in WebHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1602
diff
changeset
|
107 FileHandler fileHandler = new FileHandler(dirStr+"/site/"); |
ef9d96aeb541
use FileHandler in WebHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1602
diff
changeset
|
108 Handler handler = new ListHandler( luanHandler, fileHandler ); |
1607 | 109 handler = new ContentTypeHandler(handler); |
1605
ef9d96aeb541
use FileHandler in WebHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1602
diff
changeset
|
110 handler = new IndexHandler(handler); |
ef9d96aeb541
use FileHandler in WebHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1602
diff
changeset
|
111 DirHandler dirHandler = new DirHandler(fileHandler); |
1598 | 112 Handler notFoundHander = new NotFound(luanHandler); |
1607 | 113 notFoundHander = new ContentTypeHandler(notFoundHander); |
1602
55d7b60c074d
add DirHandler to WebHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1600
diff
changeset
|
114 handler = new ListHandler( handler, dirHandler, notFoundHander ); |
1608
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
115 Handler auth = new BasicAuthHandler(handler,"Private","admin",password); |
f7e3adae4907
add BasicAuthHandler
Franklin Schmidt <fschmidt@gmail.com>
parents:
1607
diff
changeset
|
116 handler = new RegexHandler("^/private/",auth,handler); |
1607 | 117 handler = new HeadersHandler(handler); |
1598 | 118 handler = new SafeHandler(handler); |
1600
8a717f0b7f45
add DailyRollingFileAppender.deleteAfter
Franklin Schmidt <fschmidt@gmail.com>
parents:
1599
diff
changeset
|
119 handler = new LogHandler(handler,LogHandler.dirLogger(new File(logDir),days30)); |
1598 | 120 |
1766 | 121 MyHandler myHandler = new MyHandler(handler,luanHandler); |
122 fns.set(myHandler); | |
123 return myHandler; | |
1230 | 124 } |
1315 | 125 }; |
1230 | 126 |
1627 | 127 public static LuanTable config; |
1315 | 128 private static final DomainHandler domainHandler = new DomainHandler(factory); |
1202 | 129 private static String sitesDir = null; |
1135 | 130 |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
131 public WebHandler(String dir) { |
1135 | 132 if( sitesDir != null ) |
133 throw new RuntimeException("already set"); | |
134 if( !new File(dir).exists() ) | |
135 throw new RuntimeException(); | |
1230 | 136 sitesDir = dir; |
1454 | 137 LuanLogger.initThreadLogging(); |
1135 | 138 } |
139 | |
1315 | 140 @Override public Response handle(Request request) { |
141 return domainHandler.handle(request); | |
1135 | 142 } |
143 | |
1578 | 144 public static Object callSite(String domain,String fnName,Object... args) throws LuanException { |
1598 | 145 MyHandler handler = (MyHandler)domainHandler.getHandler(domain); |
146 return handler.luanHandler.call_rpc(fnName,args); | |
1135 | 147 } |
148 | |
1315 | 149 public static void removeHandler(String domain) { |
150 domainHandler.removeHandler(domain); | |
1135 | 151 } |
152 | |
1763 | 153 public static void moveTo(String domain,String toDomain,String password) throws LuanException, IOException { |
154 toDomain = toDomain.toLowerCase(); | |
155 File fromDir = new File(sitesDir,domain); | |
156 File toDir = new File(sitesDir,toDomain); | |
157 synchronized(domain) { | |
158 if( !fromDir.exists() ) | |
159 throw new LuanException("domain not found"); | |
160 if( toDir.exists() ) | |
161 throw new LuanException("new_domain already exists"); | |
162 callSite(domain,"close_lucene",password); | |
163 removeHandler(domain); | |
164 IoUtils.move(fromDir,toDir); | |
165 } | |
166 loadHandler(toDomain); | |
167 } | |
168 | |
1330 | 169 public static void loadHandler(String domain) throws LuanException { |
170 try { | |
171 domainHandler.getHandler(domain); | |
172 } catch(LuanRuntimeException e) { | |
1335 | 173 throw (LuanException)e.getCause(); |
1330 | 174 } |
1135 | 175 } |
176 | |
1333
25746915a241
merge Luan and LuanState
Franklin Schmidt <fschmidt@gmail.com>
parents:
1332
diff
changeset
|
177 private static final void security(Luan luan,String dir) { |
1174
bdf27aa2a65c
fix luanhost security bug
Franklin Schmidt <fschmidt@gmail.com>
parents:
1136
diff
changeset
|
178 final String siteUri = "file:" + dir + "/site"; |
1330 | 179 Luan.Security security = new Luan.Security() { |
1333
25746915a241
merge Luan and LuanState
Franklin Schmidt <fschmidt@gmail.com>
parents:
1332
diff
changeset
|
180 public void check(Luan luan,LuanClosure closure,String op,Object... args) |
1330 | 181 throws LuanException |
182 { | |
183 if( op.equals("uri") ) { | |
184 String name = (String)args[0]; | |
185 if( name.startsWith("file:") ) { | |
186 if( name.contains("..") ) | |
187 throw new LuanException("Security violation - '"+name+"' contains '..'"); | |
188 if( !(name.equals(siteUri) || name.startsWith(siteUri+"/")) ) | |
189 throw new LuanException("Security violation - '"+name+"' outside of site dir"); | |
190 } | |
191 else if( name.startsWith("classpath:luan/host/") ) { | |
192 throw new LuanException("Security violation"); | |
193 } | |
194 else if( name.startsWith("os:") || name.startsWith("bash:") ) { | |
195 throw new LuanException("Security violation"); | |
196 } | |
197 } else { | |
198 String name = closure.sourceName; | |
199 if( !( | |
200 name.startsWith("luan:") | |
201 || name.startsWith("classpath:") | |
202 || name.matches("^file:[^/]+$") | |
203 ) ) | |
204 throw new LuanException("Security violation - only luan:* modules can load Java"); | |
205 if( name.equals("luan:logging/Logging") ) | |
206 throw new LuanException("Security violation - cannot reload Logging"); | |
1135 | 207 } |
208 } | |
209 }; | |
1330 | 210 Luan.setSecurity(luan,security); |
1135 | 211 } |
212 | |
1766 | 213 |
214 private static final Set<MyHandler> dontGc = Collections.newSetFromMap(new ConcurrentHashMap<MyHandler,Boolean>()); | |
215 private static final Method dontGcMethod; | |
216 static { | |
217 try { | |
218 dontGcMethod = WebHandler.Fns.class.getMethod( "dont_gc" ); | |
219 } catch(NoSuchMethodException e) { | |
220 throw new RuntimeException(e); | |
221 } | |
222 } | |
223 public static final class Fns { | |
224 private Reference<MyHandler> ref = null; | |
225 private boolean dont = false; | |
226 | |
227 private void set(MyHandler myHandler) { | |
228 if( dont ) { | |
229 dontGc.add(myHandler); | |
230 } else { | |
231 ref = new WeakReference<MyHandler>(myHandler); | |
232 } | |
233 } | |
234 | |
235 public void dont_gc() throws LuanException { | |
236 logger.info("dont_gc"); | |
237 if( ref == null ) { | |
238 dont = true; | |
239 } else { | |
240 MyHandler mh = ref.get(); | |
241 if( mh == null ) | |
242 throw new LuanException("HTTP handler has been garbage collected"); | |
243 dontGc.add(mh); | |
244 } | |
245 } | |
246 } | |
247 | |
1135 | 248 } |