use of org.folio.okapi.util.ProxyContext in project okapi by folio-org.
the class ProxyService method redirectProxy.
/**
* Extract tenantId from the request, rewrite the getPath, and proxy it.
* Expects a request to something like /_/proxy/tenant/{tid}/mod-something.
* Rewrites that to /mod-something, with the tenantId passed in the proper
* header. As there is no authtoken, this will not work for many things, but
* is needed for callbacks in the SSO systems, and who knows what else.
*
* @param ctx
*/
public void redirectProxy(RoutingContext ctx) {
ProxyContext pc = new ProxyContext(ctx);
final String origPath = ctx.request().path();
String qry = ctx.request().query();
String tid = origPath.replaceFirst("^/_/invoke/tenant/([^/ ]+)/.*$", "$1");
String newPath = origPath.replaceFirst("^/_/invoke/tenant/[^/ ]+(/.*$)", "$1");
if (qry != null && !qry.isEmpty()) {
// vert.x 3.5 clears the parameters on reroute, so we pass them in ctx
ctx.data().put(REDIRECTQUERY, qry);
logger.debug("Hiding parameters into ctx " + qry);
}
ctx.request().headers().add(XOkapiHeaders.TENANT, tid);
pc.debug("redirectProxy: '" + tid + "' '" + newPath + "'");
ctx.reroute(newPath);
logger.debug("redirectProxy: After rerouting: " + ctx.request().path() + " " + qry);
}
use of org.folio.okapi.util.ProxyContext in project okapi by folio-org.
the class ProxyService method proxyHeaders.
private void proxyHeaders(Iterator<ModuleInstance> it, ProxyContext pc, ReadStream<Buffer> stream, Buffer bcontent, ModuleInstance mi) {
RoutingContext ctx = pc.getCtx();
HttpClientRequest cReq = httpClient.requestAbs(ctx.request().method(), makeUrl(mi, ctx), res -> {
if (res.statusCode() < 200 || res.statusCode() >= 300) {
proxyResponseImmediate(pc, res, mi);
if (bcontent == null) {
stream.resume();
}
} else if (it.hasNext()) {
relayToRequest(res, pc, mi);
makeTraceHeader(mi, res.statusCode(), pc);
res.endHandler(x -> proxyR(it, pc, stream, bcontent));
} else {
relayToResponse(ctx.response(), res);
makeTraceHeader(mi, res.statusCode(), pc);
if (bcontent == null) {
stream.handler(data -> {
ctx.response().write(data);
pc.trace("ProxyHeaders request chunk '" + data.toString() + "'");
});
stream.endHandler(v -> {
ctx.response().end();
pc.trace("ProxyHeaders request end");
});
stream.exceptionHandler(e -> pc.warn("proxyHeaders: content exception ", e));
stream.resume();
} else {
pc.trace("ProxyHeaders request buf '" + bcontent + "'");
ctx.response().end(bcontent);
}
}
});
cReq.exceptionHandler(e -> {
pc.warn("proxyHeaders failure: " + mi.getUrl() + ": ", e);
pc.responseText(500, "proxyHeaders failure: " + mi.getModuleDescriptor().getId() + " " + mi.getUrl() + ": " + e + " " + e.getMessage());
});
cReq.headers().setAll(ctx.request().headers());
cReq.headers().remove("Content-Length");
cReq.end();
log(pc, cReq);
}
use of org.folio.okapi.util.ProxyContext in project okapi by folio-org.
the class ProxyService method proxy.
public void proxy(RoutingContext ctx) {
ctx.request().pause();
ReadStream<Buffer> stream = ctx.request();
// Pause the request data stream before doing any slow ops, otherwise
// it will get read into a buffer somewhere.
ProxyContext pc = new ProxyContext(ctx);
// It would be nice to pass the request-id to the client, so it knows what
// to look for in Okapi logs. But that breaks the schemas, and RMB-based
// modules will not accept the response. Maybe later...
String tenantId = tenantHeader(pc);
if (tenantId == null) {
stream.resume();
// Error code already set in ctx
return;
}
sanitizeAuthHeaders(ctx.request().headers());
tenantManager.get(tenantId, gres -> {
if (gres.failed()) {
stream.resume();
pc.responseText(400, "No such Tenant " + tenantId);
return;
}
Tenant tenant = gres.result();
moduleManager.getEnabledModules(tenant, mres -> {
if (mres.failed()) {
stream.resume();
pc.responseError(mres.getType(), mres.cause());
return;
}
List<ModuleDescriptor> enabledModules = mres.result();
String metricKey = "proxy." + tenantId + "." + ctx.request().method() + "." + ctx.normalisedPath();
DropwizardHelper.markEvent(metricKey);
List<ModuleInstance> l = getModulesForRequest(pc, enabledModules);
if (l == null) {
stream.resume();
// ctx already set up
return;
}
pc.setModList(l);
pc.logRequest(ctx, tenantId);
ctx.request().headers().add(XOkapiHeaders.URL, okapiUrl);
ctx.request().headers().remove(XOkapiHeaders.MODULE_ID);
resolveUrls(l.iterator(), res -> {
if (res.failed()) {
stream.resume();
pc.responseError(res.getType(), res.cause());
} else {
proxyR(l.iterator(), pc, stream, null);
}
});
});
});
}
use of org.folio.okapi.util.ProxyContext 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);
}
Aggregations