use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.
the class ProxyService method resolveRedirects.
private boolean resolveRedirects(ProxyContext pc, List<ModuleInstance> mods, RoutingEntry re, List<ModuleDescriptor> enabledModules, final String loop, final String uri, final String origMod) {
RoutingContext ctx = pc.getCtx();
if (re.getProxyType() == ProxyType.REDIRECT) {
// resolve redirects
boolean found = false;
final String redirectPath = re.getRedirectPath();
for (ModuleDescriptor trymod : enabledModules) {
List<RoutingEntry> rr = trymod.getProxyRoutingEntries();
for (RoutingEntry tryre : rr) {
if (tryre.match(redirectPath, ctx.request().method().name())) {
final String newUri = re.getRedirectUri(uri);
found = true;
pc.debug("resolveRedirects: " + ctx.request().method() + " " + uri + " => " + trymod + " " + newUri);
if (loop.contains(redirectPath + " ")) {
pc.responseError(500, "Redirect loop: " + loop + " -> " + redirectPath);
return false;
}
ModuleInstance mi = new ModuleInstance(trymod, tryre, newUri);
mods.add(mi);
if (!resolveRedirects(pc, mods, tryre, enabledModules, loop + " -> " + redirectPath, newUri, origMod)) {
return false;
}
}
}
}
if (!found) {
String msg = "Redirecting " + uri + " to " + redirectPath + " FAILED. No suitable module found";
pc.responseError(500, msg);
}
return found;
}
return true;
}
use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.
the class ProxyService method proxyRequestHttpClient.
private void proxyRequestHttpClient(Iterator<ModuleInstance> it, ProxyContext pc, Buffer bcontent, ModuleInstance mi) {
RoutingContext ctx = pc.getCtx();
String url = makeUrl(mi, ctx);
HttpMethod meth = ctx.request().method();
HttpClientRequest cReq = httpClient.requestAbs(meth, url, res -> {
if (res.statusCode() < 200 || res.statusCode() >= 300) {
proxyResponseImmediate(pc, res, mi);
} else if (it.hasNext()) {
makeTraceHeader(mi, res.statusCode(), pc);
pc.closeTimer();
relayToRequest(res, pc, mi);
proxyR(it, pc, null, bcontent);
} else {
relayToResponse(ctx.response(), res);
makeTraceHeader(mi, res.statusCode(), pc);
res.endHandler(x -> {
pc.closeTimer();
pc.trace("ProxyRequestHttpClient final response buf '" + bcontent + "'");
ctx.response().end(bcontent);
});
res.exceptionHandler(e -> pc.warn("proxyRequestHttpClient: res exception (b)", e));
}
});
cReq.exceptionHandler(e -> {
pc.warn("proxyRequestHttpClient failure: " + url, e);
pc.responseText(500, "proxyRequestHttpClient failure: " + mi.getModuleDescriptor().getId() + " " + mi.getUrl() + ": " + e + " " + e.getMessage());
});
cReq.headers().setAll(ctx.request().headers());
cReq.headers().remove("Content-Length");
pc.trace("ProxyRequestHttpClient request buf '" + bcontent + "'");
cReq.end(bcontent);
log(pc, cReq);
}
use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.
the class ProxyService method authResponse.
/**
* Process the auth module response. Set tokens for those modules that
* received one.
*/
private void authResponse(HttpClientResponse res, ProxyContext pc) {
String modTok = res.headers().get(XOkapiHeaders.MODULE_TOKENS);
if (modTok != null && !modTok.isEmpty()) {
JsonObject jo = new JsonObject(modTok);
for (ModuleInstance mi : pc.getModList()) {
String id = mi.getModuleDescriptor().getId();
if (jo.containsKey(id)) {
String tok = jo.getString(id);
mi.setAuthToken(tok);
pc.debug("authResponse: token for " + id + ": " + tok);
} else if (jo.containsKey("_")) {
String tok = jo.getString("_");
mi.setAuthToken(tok);
pc.debug("authResponse: Default (_) token for " + id + ": " + tok);
}
}
}
}
use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.
the class ProxyService method proxyR.
private void proxyR(Iterator<ModuleInstance> it, ProxyContext pc, ReadStream<Buffer> stream, Buffer bcontent) {
RoutingContext ctx = pc.getCtx();
if (!it.hasNext()) {
stream.resume();
pc.debug("proxyR: Not found");
// Should have been caught earlier
pc.responseText(404, "");
} else {
ModuleInstance mi = it.next();
String tenantId = ctx.request().getHeader(XOkapiHeaders.TENANT);
if (tenantId == null || tenantId.isEmpty()) {
// Should not happen, we have validated earlier
tenantId = "???";
}
String metricKey = "proxy." + tenantId + ".module." + mi.getModuleDescriptor().getId();
pc.startTimer(metricKey);
// Pass the right token
ctx.request().headers().remove(XOkapiHeaders.TOKEN);
String token = mi.getAuthToken();
if (token != null && !token.isEmpty()) {
ctx.request().headers().add(XOkapiHeaders.TOKEN, token);
}
// Pass the X-Okapi-Filter header for filters (only)
// And all kind of things for the auth filter
ctx.request().headers().remove(XOkapiHeaders.FILTER);
if (mi.getRoutingEntry().getPhase() != null) {
String pth = mi.getRoutingEntry().getPathPattern();
if (pth == null) {
pth = mi.getRoutingEntry().getPath();
}
String filt = mi.getRoutingEntry().getPhase() + " " + pth;
pc.debug("Adding " + XOkapiHeaders.FILTER + ": " + filt);
ctx.request().headers().add(XOkapiHeaders.FILTER, filt);
// The auth filter needs all kinds of special headers
if ("auth".equals(mi.getRoutingEntry().getPhase())) {
authHeaders(pc.getModList(), ctx.request().headers(), pc);
}
}
ProxyType pType = mi.getRoutingEntry().getProxyType();
if (pType != ProxyType.REDIRECT) {
pc.debug("Invoking module " + mi.getModuleDescriptor().getId() + " type " + pType + " level " + mi.getRoutingEntry().getPhaseLevel() + " path " + mi.getPath() + " url " + mi.getUrl());
}
switch(pType) {
case REQUEST_ONLY:
proxyRequestOnly(it, pc, stream, bcontent, mi);
break;
case REQUEST_RESPONSE:
proxyRequestResponse(it, pc, stream, bcontent, mi);
break;
case HEADERS:
proxyHeaders(it, pc, stream, bcontent, mi);
break;
case REDIRECT:
proxyRedirect(it, pc, stream, bcontent, mi);
break;
case INTERNAL:
proxyInternal(it, pc, stream, bcontent, mi);
break;
case REQUEST_RESPONSE_1_0:
proxyRequestResponse10(it, pc, stream, bcontent, mi);
break;
default:
// Should not happen
pc.responseText(500, "Bad proxy type '" + pType + "' in module " + mi.getModuleDescriptor().getId());
break;
}
}
}
Aggregations