Search in sources :

Example 6 with RoutingEntry

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);
}
Also used : RoutingEntry(org.folio.okapi.bean.RoutingEntry) DecodeException(io.vertx.core.json.DecodeException) Test(org.junit.Test)

Example 7 with RoutingEntry

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"));
}
Also used : RoutingEntry(org.folio.okapi.bean.RoutingEntry) Test(org.junit.Test)

Example 8 with RoutingEntry

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")));
}
Also used : RoutingEntry(org.folio.okapi.bean.RoutingEntry) ModuleInstance(org.folio.okapi.bean.ModuleInstance)

Example 9 with RoutingEntry

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;
}
Also used : ModuleDescriptor(org.folio.okapi.bean.ModuleDescriptor) RoutingEntry(org.folio.okapi.bean.RoutingEntry) HttpServerRequest(io.vertx.core.http.HttpServerRequest) ArrayList(java.util.ArrayList) ModuleInstance(org.folio.okapi.bean.ModuleInstance)

Example 10 with RoutingEntry

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;
}
Also used : ModuleDescriptor(org.folio.okapi.bean.ModuleDescriptor) RoutingContext(io.vertx.ext.web.RoutingContext) RoutingEntry(org.folio.okapi.bean.RoutingEntry) ModuleInstance(org.folio.okapi.bean.ModuleInstance)

Aggregations

RoutingEntry (org.folio.okapi.bean.RoutingEntry)10 ModuleInstance (org.folio.okapi.bean.ModuleInstance)6 ModuleDescriptor (org.folio.okapi.bean.ModuleDescriptor)3 HashMap (java.util.HashMap)2 OkapiClient (org.folio.okapi.common.OkapiClient)2 Test (org.junit.Test)2 HttpMethod (io.vertx.core.http.HttpMethod)1 HttpServerRequest (io.vertx.core.http.HttpServerRequest)1 DecodeException (io.vertx.core.json.DecodeException)1 JsonObject (io.vertx.core.json.JsonObject)1 RoutingContext (io.vertx.ext.web.RoutingContext)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 DeploymentDescriptor (org.folio.okapi.bean.DeploymentDescriptor)1 InterfaceDescriptor (org.folio.okapi.bean.InterfaceDescriptor)1 PermissionList (org.folio.okapi.bean.PermissionList)1