Warning: session_start(): open(/var/lib/php/sessions/sess_7cjd6ahosogsoci6b9sc4ocpcn, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
concept Domain {
S domain;
S moduleLibID;
S proxyDestination;
S proxyCookieChecker; // a module lib ID
bool proxyRewritePort;
bool mustBeEnabled;
toString { ret super.toString() + " " + domain; }
}
cm Eleu3 > DynEleu {
transient CRUD domainCRUD;
switchable bool verbose;
switchable bool debugNanoHTTPD;
switchable S sameSite;
start {
NanoHTTPD_debug = debugNanoHTTPD;
dbIndexingCI(Domain, 'domain);
uniqCI Domain(domain := "");
domainCRUD = new CRUD(Domain);
dm_registerAs eleuWithCRUD();
}
visualize {
var c = jtabs(
"Main", super.visualize(),
"Domains" := domainCRUD.visualize());
tablePopupMenu(domainCRUD.table(), voidfunc(JPopupMenu menu, int row) {
Domain d = domainCRUD.selected(), ret if null;
if (nempty(d.moduleLibID))
addMenuItem(menu, "Load module", rThreadEnter { dm_makeOrShow(d.moduleLibID) });
});
ret c;
}
@Override
S moduleForDomain(S domain) {
domain = dropAfterColon(domain); // drop port number
for (Domain d : domainsInMatchingOrder()) {
if (matchingDomain(d, domain)) {
S mod = findMod(d);
if (verbose) print("Domain matched: " + domain + " / " + d.domain + " => " + mod);
try answer mod;
} else
if (verbose) print("Domain not matched: " + domain + " / " + d.domain);
}
ret findMod(defaultDomain());
}
Domain defaultDomain() {
ret conceptWhereCI Domain(domain := "");
}
S findMod(Domain d) {
if (d == null || empty(d.moduleLibID)) null;
ret d.mustBeEnabled
? dm_findModuleWithParams(d.moduleLibID, enabled := true)
: dm_findModule(d.moduleLibID);
}
ServeHttp_CookieHandler makeCookieHandler() {
ServeHttp_CookieHandler cookieHandler = super.makeCookieHandler();
cookieHandler.metaParams = appendPrefixIfNempty("SameSite=", sameSite);
ret cookieHandler;
}
void onWebServersStarted :: after {
forEach(webServers(), ws -> {
print("Augmenting web server: " + ws);
ws.collectHeaderLines = true;
// session is an instance of NanoHTTPD.IHTTPSession
ws.specialHandling = session -> ctex {
temp enter();
S domain = dropPortFromHost(mapGet(session.getHeaders(), "host"));
Domain d = first(domainsInMatchingOrder(),
_d -> matchingDomain(_d, domain));
printVars(+domain, +d);
if (d == null || empty(d.proxyDestination)) false;
print("Handling proxy request to " + d.proxyDestination);
HostAndPort hap = new(d.proxyDestination);
if (nempty(d.proxyCookieChecker)) {
S cookieChecker = dm_findModule(d.proxyCookieChecker);
if (empty(cookieChecker))
fail(print("Cookie checker " + d.proxyCookieChecker + " not found, aborting request"));
NanoHTTPD.CookieHandler cookies = session.getCookies();
if (!isTrue(dm_call(cookieChecker, "checkCookie", cookies.read("cookie"), domain)))
fail(print("Cookie checker disapproves"));
}
new HandleProxyRequest hpr;
hpr.hap = hap;
hpr.session = session;
hpr.rewritePort = d.proxyRewritePort;
hpr.run();
true;
};
});
} // onWebServersStarted
bool matchingDomain(Domain d, S domain) {
ret domainIsUnder_extended(domain, d.domain);
}
class WebRequest2 extends WebRequest {
public NanoHTTPD.Response proxy(S url, bool rewriteHost, bool rewritePort) {
new HandleProxyRequest hpr;
hpr.hap = hap;
hpr.session = httpSession;
hpr.rewriteHost = rewriteHost;
hpr.rewritePort = rewritePort;
hpr.run();
null;
}
}
class HandleProxyRequest {
HostAndPort hap;
bool rewriteHost, rewritePort;
NanoHTTPD.IHTTPSession session;
new StandaloneHttpProxy proxy;
run {
S headers = windowsLineBreaks(lines(concatLists(
ll(session.getMethod() + " " + session.getFullURI() + " " + session.getProtocolVersion()),
withoutStartingWithIC("Host:", session.getHeaderLines())
)));
proxy.rewriteHostHeader = rewritePort;
proxy.forwardServerAndPort = req -> hap;
proxy.takeOverIncomingSocket(domain, session.getSocket(),
session.getInputStream(),
session.getOutputStream(),
toUtf8(printQuoted("HEADERS: ", headers))
);
}
}
@Override
WebRequest createWebRequest(NanoHTTPD.IHTTPSession httpSession,
S uri, SS params) {
ret new WebRequest2(httpSession, uri, params);
}
// API
Cl domainsInMatchingOrder() {
ret sortByCalculatedFieldICDesc(
filter(list(Domain), d -> !eqic(d.domain, "")),
d -> reversed(d.domain));
}
void addDomain(S domain, S moduleLibID, bool mustBeEnabled) {
uniq Domain(+domain, +moduleLibID, +mustBeEnabled);
}
}