Mercurial Hosting > luan
annotate src/luan/host/WebHandler.java @ 1314:51a1987b55a3
don't use NotFound handler
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 29 Jan 2019 19:10:39 -0700 |
parents | d41997776788 |
children | 5763597ca5c0 |
rev | line source |
---|---|
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
1 package luan.host; |
1135 | 2 |
3 import java.io.File; | |
4 import java.io.IOException; | |
1202 | 5 import java.lang.ref.Reference; |
6 import java.lang.ref.SoftReference; | |
7 //import java.lang.ref.WeakReference; | |
1230 | 8 import java.lang.ref.ReferenceQueue; |
1135 | 9 import java.util.Map; |
10 import java.util.HashMap; | |
11 import org.slf4j.Logger; | |
12 import org.slf4j.LoggerFactory; | |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
13 import luan.webserver.Handler; |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
14 import luan.webserver.Server; |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
15 import luan.webserver.Request; |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
16 import luan.webserver.Response; |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
17 import luan.webserver.handlers.IndexHandler; |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
18 import luan.webserver.handlers.ListHandler; |
1135 | 19 import luan.Luan; |
20 import luan.LuanState; | |
21 import luan.LuanException; | |
22 import luan.LuanTable; | |
23 import luan.LuanFunction; | |
24 import luan.modules.IoLuan; | |
25 import luan.modules.JavaLuan; | |
26 import luan.modules.PackageLuan; | |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
27 import luan.modules.http.LuanHandler; |
1135 | 28 |
29 | |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
30 public class WebHandler implements Handler { |
1135 | 31 private static final Logger logger = LoggerFactory.getLogger(WebHandler.class); |
32 | |
1230 | 33 private static class LuanRef { |
1231 | 34 private final Handler handler; |
35 private final LuanHandler luanHandler; | |
1230 | 36 |
1264 | 37 private LuanRef(Handler handler,LuanHandler luanHandler) { |
1231 | 38 this.handler = handler; |
39 this.luanHandler = luanHandler; | |
1230 | 40 } |
41 } | |
42 | |
43 private static final ReferenceQueue<LuanRef> queue = new ReferenceQueue<LuanRef>(); | |
44 | |
45 private static class MyReference extends SoftReference<LuanRef> { | |
1264 | 46 private LuanHandler luanHandler; |
1230 | 47 |
48 private MyReference(LuanRef lr) { | |
49 super(lr,queue); | |
1264 | 50 this.luanHandler = lr.luanHandler; |
1230 | 51 } |
52 } | |
53 | |
54 private static void sweep() { | |
55 while(true) { | |
56 MyReference ref = (MyReference)queue.poll(); | |
57 if( ref == null ) | |
58 return; | |
1232 | 59 //logger.info("sweep"); |
1264 | 60 ref.luanHandler.close(); |
61 ref.luanHandler = null; | |
1230 | 62 } |
63 } | |
64 | |
65 | |
1202 | 66 public static String allowJavaFileName = "allow_java"; // change for security |
1230 | 67 private static final Map<String,MyReference> siteMap = new HashMap<String,MyReference>(); |
1202 | 68 private static String sitesDir = null; |
1135 | 69 |
70 public static boolean isServing() { | |
71 return sitesDir != null; | |
72 } | |
73 | |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
74 public WebHandler(String dir) { |
1135 | 75 if( sitesDir != null ) |
76 throw new RuntimeException("already set"); | |
77 if( !new File(dir).exists() ) | |
78 throw new RuntimeException(); | |
1230 | 79 sitesDir = dir; |
1135 | 80 } |
81 | |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
82 public Response handle(Request request) { |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
83 String host = (String)request.headers.get("host"); |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
84 int i = host.indexOf(':'); |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
85 String domain = i == -1 ? host : host.substring(0,i); |
1135 | 86 // System.out.println("handle "+domain); |
1230 | 87 LuanRef lr = getSite(domain); |
88 if( lr == null ) | |
1202 | 89 return null; |
1231 | 90 return lr.handler.handle(request); |
1135 | 91 } |
92 | |
93 public static Object runLuan(String domain,String sourceText,String sourceName) throws LuanException { | |
1230 | 94 LuanRef lr = getSite(domain); |
1231 | 95 return lr.luanHandler.runLuan(sourceText,sourceName); |
1135 | 96 } |
97 | |
98 public static Object callSite(String domain,String fnName,Object... args) throws LuanException { | |
1230 | 99 LuanRef lr = getSite(domain); |
1231 | 100 return lr.luanHandler.call_rpc(fnName,args); |
1135 | 101 } |
102 | |
1230 | 103 private static LuanRef getSite(String domain) { |
1135 | 104 synchronized(siteMap) { |
1230 | 105 Reference<LuanRef> ref = siteMap.get(domain); |
106 LuanRef lr = ref==null ? null : ref.get(); | |
107 if( lr == null ) { | |
1203 | 108 //if(ref!=null) logger.info("gc "+domain); |
1135 | 109 if( sitesDir==null ) |
110 throw new NullPointerException("sitesDir"); | |
111 File dir = new File(sitesDir,domain); | |
112 if( !dir.exists() /* && !recover(dir) */ ) | |
113 return null; | |
1230 | 114 sweep(); |
1231 | 115 lr = newSite(dir.toString(),domain); |
1230 | 116 siteMap.put(domain,new MyReference(lr)); |
1135 | 117 } |
1230 | 118 return lr; |
1135 | 119 } |
120 } | |
121 /* | |
122 private static boolean recover(File dir) { | |
123 File backups = new File(dir.getParentFile().getParentFile(),"backups"); | |
124 if( !backups.exists() ) | |
125 return false; | |
126 String name = dir.getName(); | |
127 File from = null; | |
128 for( File backup : backups.listFiles() ) { | |
129 File d = new File(backup,"current/"+name); | |
130 if( d.exists() && (from==null || from.lastModified() < d.lastModified()) ) | |
131 from = d; | |
132 } | |
133 if( from == null ) | |
134 return false; | |
135 if( !from.renameTo(dir) ) | |
136 throw new RuntimeException("couldn't rename "+from+" to "+dir); | |
137 logger.info("recovered "+name+" from "+from); | |
138 return true; | |
139 } | |
140 */ | |
141 static LuanTable initLuan(LuanState luan,String dir,String domain) { | |
142 LuanTable init; | |
143 try { | |
144 init = (LuanTable)luan.eval( | |
145 "local Luan = require 'luan:Luan.luan'\n" | |
146 +"local f = Luan.load_file 'classpath:luan/host/Init.luan'\n" | |
147 +"return f('"+dir+"','"+domain+"')\n" | |
148 ); | |
149 } catch(LuanException e) { | |
150 throw new RuntimeException(e); | |
151 } | |
152 File allowJavaFile = new File(dir,"site/private/"+allowJavaFileName); | |
153 if( !allowJavaFile.exists() ) { | |
154 JavaLuan.setSecurity( luan, javaSecurity ); | |
155 IoLuan.setSecurity( luan, ioSecurity(dir) ); | |
156 } | |
157 return init; | |
158 } | |
159 | |
1231 | 160 private static LuanRef newSite(String dir,String domain) { |
1135 | 161 LuanState luan = new LuanState(); |
162 LuanTable init = initLuan(luan,dir,domain); | |
163 | |
164 String loggerRoot = (String)init.rawGet("logger_root"); | |
1263
382c444a6c77
add Http.eval_in_root and Http.handle_error
Franklin Schmidt <fschmidt@gmail.com>
parents:
1256
diff
changeset
|
165 LuanHandler luanHandler = new LuanHandler(luan,loggerRoot); |
1135 | 166 |
1185
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
167 Handler handler = luanHandler; |
94cf2576a922
implement WebHandler for nginx
Franklin Schmidt <fschmidt@gmail.com>
parents:
1182
diff
changeset
|
168 handler = new IndexHandler(handler); |
1135 | 169 |
1202 | 170 String logDir = dir + "/site/private/local/logs/web"; |
1135 | 171 new File(logDir).mkdirs(); |
172 | |
1264 | 173 return new LuanRef(handler,luanHandler); |
1135 | 174 } |
175 | |
176 public static void removeHandler(String domain) throws Exception { | |
177 synchronized(siteMap) { | |
1230 | 178 Reference<LuanRef> ref = siteMap.remove(domain); |
179 LuanRef lr = ref==null ? null : ref.get(); | |
180 if( lr != null ) { | |
1264 | 181 lr.luanHandler.close(); |
1135 | 182 } |
183 } | |
184 } | |
185 | |
186 public static void loadHandler(String domain) { | |
187 getSite(domain); | |
188 } | |
189 | |
190 private static final IoLuan.Security ioSecurity(String dir) { | |
1174
bdf27aa2a65c
fix luanhost security bug
Franklin Schmidt <fschmidt@gmail.com>
parents:
1136
diff
changeset
|
191 final String siteUri = "file:" + dir + "/site"; |
1135 | 192 return new IoLuan.Security() { |
193 public void check(LuanState luan,String name) throws LuanException { | |
194 if( name.startsWith("file:") ) { | |
195 if( name.contains("..") ) | |
196 throw new LuanException("Security violation - '"+name+"' contains '..'"); | |
1174
bdf27aa2a65c
fix luanhost security bug
Franklin Schmidt <fschmidt@gmail.com>
parents:
1136
diff
changeset
|
197 if( !(name.equals(siteUri) || name.startsWith(siteUri+"/")) ) |
1135 | 198 throw new LuanException("Security violation - '"+name+"' outside of site dir"); |
199 } | |
200 else if( name.startsWith("classpath:luan/host/") ) { | |
201 throw new LuanException("Security violation"); | |
202 } | |
203 else if( name.startsWith("os:") || name.startsWith("bash:") ) { | |
204 throw new LuanException("Security violation"); | |
205 } | |
206 } | |
207 }; | |
208 } | |
209 | |
210 private static final JavaLuan.Security javaSecurity = new JavaLuan.Security() { | |
211 public void check(LuanState luan,String name) throws LuanException { | |
1238 | 212 if( !(name.startsWith("luan:") || name.matches("^file:[^/]+$")) ) |
1135 | 213 throw new LuanException("Security violation - only luan:* modules can load Java"); |
214 if( name.equals("luan:logging/Logging") ) | |
215 throw new LuanException("Security violation - cannot reload Logging"); | |
216 } | |
217 }; | |
218 } |