OKAPI request dispatching and interface types overview

MODCATLOAD-16 - Getting issue details... STATUS

Once OKAPI gateway receives incoming request, it scans module descriptors to define modules able to handle the request further. Then, Okapi decides how to call the module depending on the "interfaceType" value in module's descriptor.

"proxy" interface type

Basically, almost all of the interfaces will be 'proxy', and if the "interfaceType" is not explicitly defined in descriptor, then the module will be a "proxy" by default. Okapi just transfers incoming request to the proxy module to handle by its own.

"system" interface type

'system' indicates interfaces that Okapi will call on its own, instead of when serving an incoming request. At the moment we have the `_tenant` interface to be called when a module is enabled for a tenant, and `_tenantpermissions` that Okapi calls when enabling a module, in order to load the permissions from the moduleDescriptor into mod-permissions. There may be more in the future.

"internal" interface type

'internal' refers to Okapi's internal module. This is a code that is linked into Okapi, and not a real module at all. All the `/_/` services like '/_/proxy', '/_/discovery', `/_/tenant` are internal modules.

"multiple" interface type

Usually, Okapi proxy allows exactly one module at once to provide a given interface. To enable Okapi to dispatch the request to any number of modules with the same interface just use "interfaceType": "multiple" in the "Provides" section of the ModuleDescriptor. It allows Okapi to deploy any number of modules with the same rest API endpoints.

Next up, the user of the interface must choose module to call by specifying HTTP header X-Okapi-Module-Id.

Also, Okapi provides an endpoint to get the list of modules which implement predefined interface: _/proxy/tenants/{tenant}/interfaces/{interface}.

Let's take a look on the simple example for module registration and call

We will define 2 modules with the same interface, deploy into Okapi and call those modules depending on X-Okapi-Module-Id header.  

  1. Lets define and register(_/proxy/modules) to Okapi module descriptor for the "Module1":

    then, deploy corresponding descriptor for the "Module1" to Okapi (_/proxy/discovery), nothing special in this section.

  2. Let's define and register(_/proxy/modules) to Okapi module descriptor for the "Module2": 
    NOTE: keep the same "id" field in "provides" section to unite all the modules with the same interface! 

    then, deploy corresponding descriptor for the "Module2" to Okapi (_/proxy/discovery), nothing special in this section.

  3. Don't forget to enable modules given above to the tenant ("diku" in our case);

  4. For now, "Module 1" and "Module 2" are listening to the same interface. It's necessary to specify X-Okapi-Module-Id header to call one of them:

    If you try to call /service endpoint without specifying module-id header, you will get 404 "No suitable module found for path /service"

  5. Okapi offers a facility which returns a list of modules that implement a given interface for a tenant (_/proxy/tenants/{tenantId}/interfaces/{interfaceId}).
    So, calling _/proxy/tenants/diku/interfaces/simple-multiple-interface you will receive:

    All the sources for both "Module1" and "Module2" mentioned before are pushed into github repo

    Running in cluster mode

    If the FOLIO application is deployed in cluster mode, a couple of instances of the same module may run. And if the module, being deployed with interface Type = multiple, has a couple of instances, we can't exactly identify which one instance will receive the incoming request. In most production deployments there will be load-balancing and failover between the module and Okapi, the way Okapi dispatches request is implementation-defined.