use of org.folio.okapi.bean.RoutingEntry in project okapi by folio-org.
the class RoutingEntryTest method test1.
@Test
public void test1() {
RoutingEntry t = new RoutingEntry();
String[] methods = new String[1];
methods[0] = "GET";
t.setPathPattern("/");
t.setMethods(methods);
assertTrue(t.match("/", "GET"));
assertFalse(t.match("/", "POST"));
assertFalse(t.match("/a", "GET"));
assertFalse(t.match("/a/", "GET"));
assertFalse(t.match("", "GET"));
assertTrue(t.match("/?query", "GET"));
assertTrue(t.match("/#x", "GET"));
t.setPathPattern("/*");
assertTrue(t.match("/", "GET"));
assertFalse(t.match("/", "POST"));
assertTrue(t.match("/a", "GET"));
assertTrue(t.match("/a/", "GET"));
assertFalse(t.match("", "GET"));
assertTrue(t.match("/?query", "GET"));
assertTrue(t.match("/#x", "GET"));
t.setPathPattern("/*/a");
assertFalse(t.match("/", "GET"));
assertFalse(t.match("/", "POST"));
assertFalse(t.match("/a", "GET"));
assertFalse(t.match("/a/", "GET"));
assertFalse(t.match("", "GET"));
assertFalse(t.match("/?query", "GET"));
assertFalse(t.match("/#x", "GET"));
assertTrue(t.match("/b/a", "GET"));
assertTrue(t.match("/c/b/a", "GET"));
t.setPathPattern("/a/{id}");
assertFalse(t.match("/", "GET"));
assertFalse(t.match("/", "POST"));
assertFalse(t.match("/a", "GET"));
assertFalse(t.match("/a/", "GET"));
assertFalse(t.match("", "GET"));
assertFalse(t.match("/?query", "GET"));
assertFalse(t.match("/#x", "GET"));
assertTrue(t.match("/a/b", "GET"));
assertTrue(t.match("/a/0-9", "GET"));
assertFalse(t.match("/a/b/", "GET"));
assertFalse(t.match("/a/b/", "GET"));
assertFalse(t.match("/a/b/c", "GET"));
t.setPathPattern("/a/{id}/c");
assertFalse(t.match("/", "GET"));
assertFalse(t.match("/", "POST"));
assertFalse(t.match("/a", "GET"));
assertFalse(t.match("/a/", "GET"));
assertFalse(t.match("", "GET"));
assertFalse(t.match("/?query", "GET"));
assertFalse(t.match("/#x", "GET"));
assertFalse(t.match("/a/b", "GET"));
assertFalse(t.match("/a/0-9", "GET"));
assertFalse(t.match("/a/b/", "GET"));
assertFalse(t.match("/a/b/", "GET"));
assertTrue(t.match("/a/b/c", "GET"));
boolean caught = false;
try {
t.setPathPattern("/a{a{");
} catch (DecodeException e) {
caught = true;
}
assertTrue(caught);
caught = false;
try {
t.setPathPattern("/a{");
} catch (DecodeException e) {
caught = true;
}
assertTrue(caught);
caught = false;
try {
t.setPathPattern("/?a=b");
} catch (DecodeException e) {
caught = true;
}
assertTrue(caught);
caught = false;
try {
t.setPathPattern("/a.b");
} catch (DecodeException e) {
caught = true;
}
assertTrue(caught);
caught = false;
try {
t.setPathPattern("/a\\b");
} catch (DecodeException e) {
caught = true;
}
assertTrue(caught);
caught = false;
try {
t.setPathPattern("/a{:}b");
} catch (DecodeException e) {
caught = true;
}
assertTrue(caught);
caught = false;
try {
t.setPathPattern("/a{}b");
} catch (DecodeException e) {
caught = true;
}
assertFalse(caught);
}
use of org.folio.okapi.bean.RoutingEntry in project okapi by folio-org.
the class RoutingEntryTest method test2.
@Test
public void test2() {
RoutingEntry t = new RoutingEntry();
String[] methods = new String[1];
methods[0] = "GET";
t.setMethods(methods);
t.setPathPattern("/req");
t.setRedirectPath("/res");
assertTrue(t.match("/req", "GET"));
assertEquals("/res", t.getRedirectUri("/req"));
assertEquals("/res?abc", t.getRedirectUri("/req?abc"));
assertEquals("/res?abc#a", t.getRedirectUri("/req?abc#a"));
assertEquals("/res#a", t.getRedirectUri("/req#a"));
t.setPathPattern("/req/{id}");
t.setRedirectPath("/res/1234");
assertTrue(t.match("/req/2", "GET"));
assertEquals("/res/1234", t.getRedirectUri("/req/2"));
t.setPathPattern("/req/{id}/bongo");
t.setRedirectPath("/res/1234/a/b");
assertTrue(t.match("/req/q/bongo", "GET"));
assertEquals("/res/1234/a/b", t.getRedirectUri("/req/2/bongo"));
t.setPathPattern("/req/*/s");
t.setRedirectPath("/res/1234");
assertTrue(t.match("/req/a/s", "GET"));
assertEquals("/res/1234", t.getRedirectUri("/req/a/s"));
}
use of org.folio.okapi.bean.RoutingEntry in project okapi by folio-org.
the class TenantManager method getTenantInterface1.
private void getTenantInterface1(InterfaceDescriptor pi, ModuleDescriptor md, Handler<ExtendedAsyncResult<ModuleInstance>> fut) {
if (!"1.0".equals(pi.getVersion())) {
fut.handle(new Failure<>(USER, "Interface _tenant must be version 1.0 "));
return;
}
if ("system".equals(pi.getInterfaceType())) {
// looks like a new type
List<RoutingEntry> res = pi.getAllRoutingEntries();
if (!res.isEmpty()) {
for (RoutingEntry re : res) {
if (re.match(null, "POST")) {
if (re.getPath() != null) {
logger.debug("findTenantInterface: found path " + re.getPath());
fut.handle(new Success<>(new ModuleInstance(md, re, re.getPath())));
return;
}
if (re.getPathPattern() != null) {
logger.debug("findTenantInterface: found pattern " + re.getPathPattern());
fut.handle(new Success<>(new ModuleInstance(md, re, re.getPathPattern())));
return;
}
}
}
}
}
logger.warn("Module '" + md.getId() + "' uses old-fashioned tenant " + "interface. Define InterfaceType=system, and add a RoutingEntry." + " Falling back to calling /_/tenant.");
fut.handle(new Success<>(new ModuleInstance(md, null, "/_/tenant")));
}
use of org.folio.okapi.bean.RoutingEntry in project okapi by folio-org.
the class ProxyService method getModulesForRequest.
/**
* Builds the pipeline of modules to be invoked for a request.
* Sets the
* default authToken for each ModuleInstance. Later, these can be overwritten
* by the ModuleTokens from the auth, if needed.
*
* @param pc
* @param enabledModules modules enabled for the current tenant
* @return a list of ModuleInstances. In case of error, sets up ctx and
* returns null.
*/
private List<ModuleInstance> getModulesForRequest(ProxyContext pc, List<ModuleDescriptor> enabledModules) {
List<ModuleInstance> mods = new ArrayList<>();
HttpServerRequest req = pc.getCtx().request();
final String id = req.getHeader(XOkapiHeaders.MODULE_ID);
pc.debug("getMods: Matching " + req.method() + " " + req.absoluteURI());
for (ModuleDescriptor md : enabledModules) {
pc.debug("getMods: looking at " + md.getId());
List<RoutingEntry> rr = null;
if (id == null) {
rr = md.getProxyRoutingEntries();
} else if (id.equals(md.getId())) {
rr = md.getMultiRoutingEntries();
}
if (rr != null) {
for (RoutingEntry re : rr) {
if (match(re, req)) {
ModuleInstance mi = new ModuleInstance(md, re, req.uri());
mi.setAuthToken(pc.getCtx().request().headers().get(XOkapiHeaders.TOKEN));
mods.add(mi);
if (!resolveRedirects(pc, mods, re, enabledModules, "", req.uri(), "")) {
return null;
}
pc.debug("getMods: Added " + md.getId() + " " + re.getPathPattern() + " " + re.getPath() + " " + re.getPhase() + "/" + re.getLevel());
}
}
}
}
Comparator<ModuleInstance> cmp = (ModuleInstance a, ModuleInstance b) -> a.getRoutingEntry().getPhaseLevel().compareTo(b.getRoutingEntry().getPhaseLevel());
mods.sort(cmp);
// Check that our pipeline has a real module in it, not just filters,
// so that we can return a proper 404 for requests that only hit auth
pc.debug("Checking filters for " + req.absoluteURI());
boolean found = false;
for (ModuleInstance inst : mods) {
pc.debug("getMods: Checking " + inst.getRoutingEntry().getPathPattern() + " " + "'" + inst.getRoutingEntry().getPhase() + "' " + "'" + inst.getRoutingEntry().getLevel() + "' ");
if (inst.getRoutingEntry().getPhase() == null) {
// No real handler should have a phase any more.
found = true;
// It has been deprecated for a long time, and never made any sense anyway.
// The auth filter, the only one we have, uses phase 'auth'
}
}
if (!found) {
if (// If we defaulted to supertenant,
"-".equals(pc.getTenant()) && !req.path().startsWith("/_/")) {
// and not wrong okapi request
// The /_/ test is to make sure we report same errors as before internalModule stuff
pc.responseText(403, "Missing Tenant");
return null;
} else {
pc.responseError(404, "No suitable module found for path " + req.path());
return null;
}
}
return mods;
}
use of org.folio.okapi.bean.RoutingEntry 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;
}
Aggregations