static new ThreadLocal MyHTTPD_headers; static new ThreadLocal MyHTTPD_current; sclass MyHTTPD extends NanoHTTPD { *(int port) { super(port); } O onServe, onEndServe; volatile long requests; transient IF0 enter; O serveFunction = func(S uri, SS parms) { callHtmlMethod2(getMainClass(), uri, parms) }; sclass Serving { S uri; SS header, parms, files; } Set currentlyServing = synchroSet(); public Response serve(S uri, Method method, SS header, SS parms, SS files) ctex { temp callF(enter); ++requests; temp tempSetThreadLocal(MyHTTPD_current, this); Serving serving = nu(Serving.class, +uri, +header, +parms, +files); currentlyServing.add(serving); pcallF(onServe, serving); try { S remoteAddr = getClientIPFromHeaders(header); S host = header.get("host"); print(formatDateAndTime() + " Serving URI: " + quote((nempty(host) ? "//" + host : "") + uri) + " to: " + remoteAddr); /*if (nempty(remoteAddr) && isTrue(callOpt(mc(), "isBlockedIP", remoteAddr))) { print("BLOCKED IP."); ret serve404(); }*/ try { Response response = cast callOpt(getMainClass(), "serve", uri, method, header, parms, files); if (response != null) ret response; O html; MyHTTPD_headers.set(header); try { html = callF(serveFunction, uri, parms); } finally { MyHTTPD_headers.set(null); } if (html != null) ret html instanceof S ? serveHTML((S) html) : (NanoHTTPD.Response) html; ret serve404(); } catch (Throwable e) { printStackTrace(e); ret serveHTML("ERROR."); } } finally { pcallF(onEndServe, serving); currentlyServing.remove(serving); } } }