Much of the programming is driven by the OpenAPI specification. This is why you should always include the latest OpenAPI specification in
Launch.start looks at the
config.json file, gets the
versions object and loads the corresponding OpenAPI specs into memory with
io.vertx.ext.web.api.contract.openapi3.OpenAPI3RouterFactoryintrospects the OpenAPI specs.
- It automatically creates routes based on what is there in the OpenAPIs.
- It is set to require security handlers matching spec.
- The HttpListener verticle’s
listenerStart()method loads handlers* in com.hcl.domino.keep.handlers package, sending messages to “keep.request.” + operationId (e.g “keep.request.createlocaluser”).
DominoDefaultVerticleverticle instances load corresponding dbrequest handlers* in com.hcl.domino.keep.dbrequests package consuming messages for “keep.request.” + operationId (e.g. “keep.request.createlocaluser”).
- The OpenAPI3RouterFactory automatically:
- validates that only valid HTTP methods are used.
- validates HTTP request content-type.
- validates HTTP request content matches contract (throwing Bad Request, HTTP 400).
- All verticles are loaded based on config in
- HttpListener loads handlers for each version by introspecting the RestAPI object in the config.json, which identifies the URL route to apply for each version and where to find the handler. The config defines a package for each OpenAPI spec, so it looks for a handler in that package whose class name is the operationId (first letter upper-cased). If not found the default class defined for that OpenAPI spec in the config is used, in our case always
com.hcl.domino.keep.handlers.DefaultJsonHandler. If the request body or response body are not “application/json” a custom handler will need adding.
DominoDefaultVerticleinstances loads verticles as defined in config.json’s package, based on the tag in an OpenAPI spec. E.g. for an “admin” tagged OpenAPI endpoint, they’re loaded only by an instance of DominoDefaultVerticle, loading handlers in the
com.hcl.domino.keep.dbrequests.adminpackage, using a class whose name is the operationId (first letter upper-cased). Consequently tags need to be unique across all OpenAPI specs.
- AbstractAPIHandler records the request in the metrics and extracts bearer token from Authorization header and “db” query parameter in
- It adds in the operation id from the OpenAPI spec in
requestBodyFromAllParams()to merge in content from Vert.x’s RoutingContext’s parsed parameters - cookies, headers, query parameters, path parameters and form. The body is also adding in as “payload”.
- A handler’s
listenForResponse()creates an EventBusRequestObservable to route onto the Event Bus and listen for data coming back, streaming it onto the HttpServerResponse.
The router validates:
- An invalid endpoint throws a 404 error.
- An endpoint with a missing handler. The security handlers manage authorization:
- A missing Authorization header, when required, immediately throws a 401 error.
- For endpoints requiring “jwt” authentication, the JWT token is checked against the expired tokens or logged out users, throwing a 401 error.
- An invalid Authorization header, when required, throwing a 401 error. The OpenAPI router also validates against the spec:
- Invalid methods (GET on a POST endpoint) throw a 405 error.
- Body that is not valid JSON or missing throws a 400 error with the message “$: string found, object expected”.
- Based on the RequestOptionFlags defined for the relevant handler, an ill-formed Authorization header and/or “db” query parameter are validated by
AbstractAPIHandlerbefore even parsing the RoutingContext parameters. An HTTP 400 error is thrown.
- If nothing has been configured yet to consume messages for the operationId, the handler’s
listenForResponse()method throws a 500 response.
- The message is then passed to the NSF handler for asynchronous processing.
- Annotations in the NSF handler are used to validate that the user has a minimum ACL level access, flags and/or roles to the relevant database.
processmethod of NSF handlers (in
com.hc.domino.keep.dbrequestspackages) may apply additional validation.