Interface WebClientDiscovery
- All Superinterfaces:
NamedService,NamedService,RuntimeType.Api<WebClientDiscoveryConfig>,WebClientService
WebClientService that intercepts certain requests and uses Helidon Discovery where
appropriate to discover endpoints for those requests, rerouting them as necessary.
WebClientDiscovery instances are normally created by WebClientDiscoveryProvider instances, and are not typically used directly by end users.
The specification for the handle(Chain, WebClientServiceRequest) method fully specifies the required
behavior of conforming implementations of this interface, and further describes the implementation-specific behavior
of WebClientDiscovery instances returned from invocations of the create(WebClientDiscoveryConfig)
method.
Logging
Implementations returned by invocations of the create(WebClientDiscoveryConfig) method, and any of their
internal supporting classes, will use Loggers whose names begin with io.helidon.webclient.discovery..
Logging output is particularly important to monitor because as a general rule discovery integrations must strive to be resilient in the presence of failures.
- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from interface io.helidon.webclient.spi.WebClientService
WebClientService.Chain -
Method Summary
Modifier and TypeMethodDescriptionbuilder()A convenience method that returns the result of invoking theWebClientDiscoveryConfig.builder()method.static WebClientDiscoverycreate(WebClientDiscoveryConfig prototype) Returns a newWebClientDiscoveryimplementation configured with the suppliedprototype.static WebClientDiscoverycreate(Consumer<WebClientDiscoveryConfig.Builder> consumer) A convenience method that calls thebuilder()method, updates it using the suppliedConsumer, invokes itsbuild()method, and returns the result.handle(WebClientService.Chain chain, WebClientServiceRequest request) Handles the suppliedWebClientServiceRequestby using thisWebClientDiscovery's Helidon Discovery-related configuration to discover aURIappropriate for the request, and altering theClientUrias necessary with the discovered information before continuing with the request.default Stringname()Returns the determinate name of thisWebClientServiceimplementation (normallydiscovery).default Stringtype()Returns the determinate type of thisWebClientServiceimplementation (discoveryby default).Methods inherited from interface io.helidon.builder.api.RuntimeType.Api
prototype
-
Method Details
-
handle
Handles the suppliedWebClientServiceRequestby using thisWebClientDiscovery's Helidon Discovery-related configuration to discover aURIappropriate for the request, and altering theClientUrias necessary with the discovered information before continuing with the request.The specification of this method is described below, followed by a description of its default implementation.
Specification
Any implementation of this method must:
- Deterministically decide whether the supplied
WebClientServiceRequestis one for which Helidon Discovery is appropriate. If it is not, the implementation must callchain.proceed(request)and return the result. - Deterministically produce a discovery name and a default URI appropriate for the
supplied
WebClientServiceRequestto use during the discovery process. If either cannot be produced for any reason, the implementation must callchain.proceed(request)and return the result. - Use the discovery name and default URI in a discovery request. If this cannot happen for any reason, the implementation must call
chain.proceed(request)and return the result. - Select a URI from the discovered response (the discovered URI). If this cannot happen for any
reason, the implementation must call
chain.proceed(request)and return the result. - Deterministically alter the supplied
WebClientServiceRequest'sClientUriwith information supplied by the discovered URI. If this cannot happen for any reason, the implementation must callchain.proceed(request)and return the result. - Call
chain.proceed(request)and return the result.
Implementation Behavior
The (default) behavior of this method, as implemented in instances of
WebClientDiscoveryreturned from thecreate(WebClientDiscoveryConfig)method, conforms to the specification, and is described below. This implementation-specific behavior may change in subsequent revisions of this interface and its cooperating classes.Finding and using discovery-related information suitable for the supplied
WebClientServiceRequestproceeds as follows, with examples:- Upon initial
WebClientDiscoveryimplementation instantiation, the entries of its prototype'sprefixUrisMapare normalized and sorted, such that entries containing longer (more specific)URIs precede shorter ones (less specific). This operation happens exactly once. - If the
prefixUrisMapis empty, then discovery will never be used, andchain.proceed(request)is invoked, and the result is returned. - In a loop, for each such
URI(e.g.http://service1.example.com), proceeding from the longest (most specific) one to the shortest (least specific) one:- a prefix URI is created from it, following the logic that Helidon WebClient uses elsewhere
internally to create URIs, for overall fidelity.
- Note that this logic may add additional information, or change existing
information; e.g. in this example the URI would be
http://service1.example.com:80/; note the explicit port (80) and non-empty path that is now/instead of the empty string. SeeClientUri.create(URI)andClientUri.toUri()for an explanation of this logic.
- Note that this logic may add additional information, or change existing
information; e.g. in this example the URI would be
- For each such prefix URI, an attempt is made to relativize the original
ClientUriagainst it:- The original
ClientUri'sURI(e.g.http://service1.example.com:80/foo) in normal form is relativized against the normalized prefix URI (e.g.http://service1.example.com:80/).- Note that for
ClientUri-implementation-related reasons, the originalClientUriwill always be absolute, its host and port will always be defined, and its path will never be empty, even if the user did not specify any of this explicitly.
- Note that for
- If relativization yields anything other than a simple raw path, the prefix URI is skipped and the loop continues.
- Otherwise, the loop exits with:
- the prefix URI (e.g.
http://service1.example.com:80/), - its corresponding discovery name (e.g.
S1), and - the result of relativization (the remaining raw path, e.g.
foo).
- the prefix URI (e.g.
- The original
- a prefix URI is created from it, following the logic that Helidon WebClient uses elsewhere
internally to create URIs, for overall fidelity.
- If no prefix URI was found for any reason, discovery is not needed,
chain.proceed(request)is invoked, and the result is returned. - The
Discoveryinstance supplied by the prototype is used to issue a discovery request using the discovery name (e.g.S1) and prefix URI (e.g.http://service1.example.com:80/). The first of the URIs returned is the discovered URI; seeDiscovery.uris(String, java.net.URI)for more details. For this example, presume the discovered URI is, e.g.,http://23.192.228.84:80/v1/. - A new raw path is formed by first resolving
the remaining raw path (e.g.
foo) against the discovered URI (e.g.http://23.192.228.84:80/v1/), yielding, e.g.,http://23.192.228.84:80/v1/foo, and then acquiring its raw path (e.g./v1/foo). - If defined, the scheme (e.g.
http), host (e.g.23.192.228.84), and port (e.g.80) of the discovered URI (e.g.http://23.192.228.84:80/v1) are installed on the originalClientUriusing itsscheme(String),host(String)andport(int)methods. - The new raw path (e.g.
/v1/foo) is installed on the originalClientUriusing itspath(String)method. - This results in the final URI (e.g.
http://23.192.228.84:80/v1/foo).
Finally, including when any error is encountered,
chain.proceed(request)is invoked, and the result is returned.Configuration Examples
A minimal example of (YAML) configuration follows:
client: # see the Helidon Configuration Reference for WebClient services: discovery: prefix-uris: S1: http://service1.example.com
In this example, original
ClientUris beginning withhttp://service1.example.com:80/(note the added/explicit port and path) will be subject to discovery, usingS1as the discovery name; all others will be passed through with no discovery-related action being taken.- Specified by:
handlein interfaceWebClientService- Parameters:
chain- aWebClientService.Chainrequest- aWebClientServiceRequest- Returns:
- the result of invoking the
proceed(WebClientServiceRequest)method on the suppliedWebClientService.Chain - Throws:
NullPointerException- if any argument isnull- See Also:
- Deterministically decide whether the supplied
-
name
Returns the determinate name of thisWebClientServiceimplementation (normallydiscovery).The default implementation of this method returns the result of invoking the
name()method on thisWebClientDiscovery's prototype.- Specified by:
namein interfaceNamedService- Specified by:
namein interfaceNamedService- Specified by:
namein interfaceWebClientService- Returns:
- this
WebClientDiscovery's determinate name - See Also:
-
type
Returns the determinate type of thisWebClientServiceimplementation (discoveryby default).The default implementation of this method returns
discovery.- Specified by:
typein interfaceNamedService- Specified by:
typein interfaceNamedService- Specified by:
typein interfaceWebClientService- Returns:
discoverywhen invoked- See Also:
-
builder
A convenience method that returns the result of invoking theWebClientDiscoveryConfig.builder()method.- Returns:
- a non-
nullWebClientDiscoveryConfig.Builder - See Also:
-
create
A convenience method that calls thebuilder()method, updates it using the suppliedConsumer, invokes itsbuild()method, and returns the result.- Parameters:
consumer- aConsumerofWebClientDiscoveryConfig.Builderinstances; must not benull- Returns:
- a new
WebClientDiscoveryimplementation; nevernull - Throws:
NullPointerException- ifconsumerisnull- See Also:
-
create
Returns a newWebClientDiscoveryimplementation configured with the suppliedprototype.This method is most commonly called by the
WebClientDiscoveryConfig.Builder.build()method, which supplies it with the return value of an invocation of itsWebClientDiscoveryConfig.Builder.buildPrototype()method.- Parameters:
prototype- aWebClientDiscoveryConfig; must not benull- Returns:
- a new
WebClientDiscoveryimplementation - Throws:
NullPointerException- ifprototypeisnull- See Also:
-