Search in sources :

Example 1 with ModuleInstance

use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.

the class ProxyContext method logRequest.

/* Helpers for logging and building responses */
public final void logRequest(RoutingContext ctx, String tenant) {
    StringBuilder mods = new StringBuilder();
    if (modList != null && !modList.isEmpty()) {
        for (ModuleInstance mi : modList) {
            mods.append(" ").append(mi.getModuleDescriptor().getId());
        }
    }
    logger.info(reqId + " REQ " + ctx.request().remoteAddress() + " " + tenant + " " + ctx.request().method() + " " + ctx.request().path() + mods.toString());
}
Also used : ModuleInstance(org.folio.okapi.bean.ModuleInstance)

Example 2 with ModuleInstance

use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.

the class ProxyService method resolveUrls.

private void resolveUrls(Iterator<ModuleInstance> it, Handler<ExtendedAsyncResult<Void>> fut) {
    if (!it.hasNext()) {
        fut.handle(new Success<>());
    } else {
        ModuleInstance mi = it.next();
        if (mi.getRoutingEntry().getProxyType() == ProxyType.INTERNAL) {
            mi.setUrl("");
            resolveUrls(it, fut);
            return;
        }
        discoveryManager.get(mi.getModuleDescriptor().getId(), res -> {
            if (res.failed()) {
                fut.handle(new Failure<>(res.getType(), res.cause()));
            } else {
                DeploymentDescriptor instance = pickInstance(res.result());
                if (instance == null) {
                    fut.handle(new Failure<>(NOT_FOUND, "No running module instance found for " + mi.getModuleDescriptor().getId()));
                    return;
                }
                mi.setUrl(instance.getUrl());
                resolveUrls(it, fut);
            }
        });
    }
}
Also used : DeploymentDescriptor(org.folio.okapi.bean.DeploymentDescriptor) ModuleInstance(org.folio.okapi.bean.ModuleInstance)

Example 3 with ModuleInstance

use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.

the class ProxyService method authHeaders.

/**
 * Set up special auth headers. Get the auth bits from the module list into
 * X-Okapi-Permissions-Required and X-Okapi-Permissions-Desired headers. Also
 * X-Okapi-Module-Permissions for each module that has such.
 */
private void authHeaders(List<ModuleInstance> modlist, MultiMap requestHeaders, ProxyContext pc) {
    // Sanitize important headers from the incoming request
    sanitizeAuthHeaders(requestHeaders);
    Set<String> req = new HashSet<>();
    Set<String> want = new HashSet<>();
    Set<String> extraperms = new HashSet<>();
    // !!
    Map<String, String[]> modperms = new HashMap<>(modlist.size());
    for (ModuleInstance mod : modlist) {
        RoutingEntry re = mod.getRoutingEntry();
        String[] reqp = re.getPermissionsRequired();
        if (reqp != null) {
            req.addAll(Arrays.asList(reqp));
        }
        String[] wap = re.getPermissionsDesired();
        if (wap != null) {
            want.addAll(Arrays.asList(wap));
        }
        String[] modp = re.getModulePermissions();
        if (modp != null) {
            if (re.getProxyType() == ProxyType.REDIRECT) {
                extraperms.addAll(Arrays.asList(modp));
            } else {
                modperms.put(mod.getModuleDescriptor().getId(), modp);
            }
        }
    }
    // mod loop
    if (!req.isEmpty()) {
        pc.debug("authHeaders: " + XOkapiHeaders.PERMISSIONS_REQUIRED + " " + String.join(",", req));
        requestHeaders.add(XOkapiHeaders.PERMISSIONS_REQUIRED, String.join(",", req));
    }
    if (!want.isEmpty()) {
        pc.debug("authHeaders: " + XOkapiHeaders.PERMISSIONS_DESIRED + " " + String.join(",", want));
        requestHeaders.add(XOkapiHeaders.PERMISSIONS_DESIRED, String.join(",", want));
    }
    // Add the X-Okapi-Module-Permissions even if empty. That causes auth to return
    // an empty X-Okapi-Module-Token, which will tell us that we have done the mod
    // perms, and no other module should be allowed to do the same.
    String mpj = Json.encode(modperms);
    pc.debug("authHeaders: " + XOkapiHeaders.MODULE_PERMISSIONS + " " + mpj);
    requestHeaders.add(XOkapiHeaders.MODULE_PERMISSIONS, mpj);
    if (!extraperms.isEmpty()) {
        String epj = Json.encode(extraperms);
        pc.debug("authHeaders: " + XOkapiHeaders.EXTRA_PERMISSIONS + " " + epj);
        requestHeaders.add(XOkapiHeaders.EXTRA_PERMISSIONS, epj);
    }
}
Also used : RoutingEntry(org.folio.okapi.bean.RoutingEntry) HashMap(java.util.HashMap) ModuleInstance(org.folio.okapi.bean.ModuleInstance) HashSet(java.util.HashSet)

Example 4 with ModuleInstance

use of org.folio.okapi.bean.ModuleInstance in project okapi by folio-org.

the class ProxyService method authForSystemInterface.

/**
 * Helper to get a new authtoken before invoking doCallSystemInterface.
 */
private void authForSystemInterface(ModuleDescriptor authMod, RoutingEntry filt, String tenantId, ModuleInstance inst, String request, ProxyContext pc, Handler<ExtendedAsyncResult<OkapiClient>> fut) {
    pc.debug("Calling doCallSystemInterface to get auth token");
    RoutingEntry re = inst.getRoutingEntry();
    String modPerms = "";
    if (re != null) {
        String[] modulePermissions = re.getModulePermissions();
        Map<String, String[]> mpMap = new HashMap<>();
        if (modulePermissions != null) {
            mpMap.put(inst.getModuleDescriptor().getId(), modulePermissions);
            logger.debug("authForSystemInterface: Found modPerms:" + modPerms);
        } else {
            logger.debug("authForSystemInterface: Got RoutingEntry, but null modulePermissions");
        }
        modPerms = Json.encode(mpMap);
    } else {
        logger.debug("authForSystemInterface: re is null, can't find modPerms");
    }
    ModuleInstance authInst = new ModuleInstance(authMod, filt, inst.getPath());
    doCallSystemInterface(tenantId, null, authInst, modPerms, "", pc, res -> {
        if (res.failed()) {
            pc.warn("Auth check for systemInterface failed!");
            fut.handle(new Failure<>(res.getType(), res.cause()));
            return;
        }
        OkapiClient cli = res.result();
        String deftok = cli.getRespHeaders().get(XOkapiHeaders.TOKEN);
        logger.debug("authForSystemInterface:" + Json.encode(cli.getRespHeaders().entries()));
        String modTok = cli.getRespHeaders().get(XOkapiHeaders.MODULE_TOKENS);
        JsonObject jo = new JsonObject(modTok);
        String token = jo.getString(inst.getModuleDescriptor().getId(), deftok);
        logger.debug("authForSystemInterface: Got token " + token);
        doCallSystemInterface(tenantId, token, inst, null, request, pc, fut);
    });
}
Also used : RoutingEntry(org.folio.okapi.bean.RoutingEntry) OkapiClient(org.folio.okapi.common.OkapiClient) HashMap(java.util.HashMap) JsonObject(io.vertx.core.json.JsonObject) ModuleInstance(org.folio.okapi.bean.ModuleInstance)

Example 5 with ModuleInstance

use of org.folio.okapi.bean.ModuleInstance 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);
}
Also used : HttpServerRequest(io.vertx.core.http.HttpServerRequest) Json(io.vertx.core.json.Json) Arrays(java.util.Arrays) ModuleDescriptor(org.folio.okapi.bean.ModuleDescriptor) XOkapiHeaders(org.folio.okapi.common.XOkapiHeaders) NOT_FOUND(org.folio.okapi.common.ErrorType.NOT_FOUND) MultiMap(io.vertx.core.MultiMap) OkapiToken(org.folio.okapi.common.OkapiToken) HashMap(java.util.HashMap) Random(java.util.Random) RoutingContext(io.vertx.ext.web.RoutingContext) Tenant(org.folio.okapi.bean.Tenant) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) OkapiClient(org.folio.okapi.common.OkapiClient) OkapiLogger(org.folio.okapi.common.OkapiLogger) HttpClientRequest(io.vertx.core.http.HttpClientRequest) HttpClientResponse(io.vertx.core.http.HttpClientResponse) Matcher(java.util.regex.Matcher) DeploymentDescriptor(org.folio.okapi.bean.DeploymentDescriptor) ProxyType(org.folio.okapi.bean.RoutingEntry.ProxyType) Map(java.util.Map) RoutingEntry(org.folio.okapi.bean.RoutingEntry) ProxyContext(org.folio.okapi.util.ProxyContext) ReadStream(io.vertx.core.streams.ReadStream) DiscoveryManager(org.folio.okapi.discovery.DiscoveryManager) ExtendedAsyncResult(org.folio.okapi.common.ExtendedAsyncResult) JsonObject(io.vertx.core.json.JsonObject) Failure(org.folio.okapi.common.Failure) InternalModule(org.folio.okapi.web.InternalModule) HttpClientOptions(io.vertx.core.http.HttpClientOptions) Logger(io.vertx.core.logging.Logger) USER(org.folio.okapi.common.ErrorType.USER) Iterator(java.util.Iterator) Vertx(io.vertx.core.Vertx) Set(java.util.Set) Success(org.folio.okapi.common.Success) ModuleInstance(org.folio.okapi.bean.ModuleInstance) List(java.util.List) INTERNAL(org.folio.okapi.common.ErrorType.INTERNAL) Buffer(io.vertx.core.buffer.Buffer) HttpMethod(io.vertx.core.http.HttpMethod) HttpServerResponse(io.vertx.core.http.HttpServerResponse) DropwizardHelper(org.folio.okapi.util.DropwizardHelper) Pattern(java.util.regex.Pattern) Handler(io.vertx.core.Handler) Comparator(java.util.Comparator) HttpClient(io.vertx.core.http.HttpClient) RoutingContext(io.vertx.ext.web.RoutingContext) HttpClientRequest(io.vertx.core.http.HttpClientRequest)

Aggregations

ModuleInstance (org.folio.okapi.bean.ModuleInstance)14 RoutingEntry (org.folio.okapi.bean.RoutingEntry)8 JsonObject (io.vertx.core.json.JsonObject)5 ModuleDescriptor (org.folio.okapi.bean.ModuleDescriptor)5 RoutingContext (io.vertx.ext.web.RoutingContext)4 HashMap (java.util.HashMap)4 Buffer (io.vertx.core.buffer.Buffer)3 HttpServerRequest (io.vertx.core.http.HttpServerRequest)3 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 DeploymentDescriptor (org.folio.okapi.bean.DeploymentDescriptor)3 ProxyType (org.folio.okapi.bean.RoutingEntry.ProxyType)3 Tenant (org.folio.okapi.bean.Tenant)3 OkapiClient (org.folio.okapi.common.OkapiClient)3 Handler (io.vertx.core.Handler)2 MultiMap (io.vertx.core.MultiMap)2 Vertx (io.vertx.core.Vertx)2 HttpClient (io.vertx.core.http.HttpClient)2 HttpClientOptions (io.vertx.core.http.HttpClientOptions)2 HttpClientRequest (io.vertx.core.http.HttpClientRequest)2