Class RestClient
io.inversion.Action with some superpowers.
RestClient gives you easy or built in:
- fluent asynchronous response handler api
- automatic retry support
- header forwarding w/ whitelists and blacklists
- url query string param forwarding w/ whitelist and blacklists
- lazy runtime host url construction through lookup of "${name}.url" in the environment
- dynamic host url variables - any "${paramName}" tokens in the host url will be replaced with Chain.peek.getRequest().getUrl().getParam(paramName).
- short circuit remote calls or transform Requests/Responses with a single
override of
doRequest(Request)
Transforming requests / responses
You can easily override the doRequest(Request) method to potentially short circuit calls or perform request/response transforms.
For example:
protected RestClient client = new RestClient("myservice")
{
protected Response doRequest(Request request)
{
if(checkMyCondition(request))
{
//-- short circuit the remote call "faking" a
//-- remote 200 response (the default status code for a Response)
return new Response(request.getUrl());
}
else
{
doMyRequestTransformation(request);
Response response = super.getResponse(request);
doMyResponseTransformation(response);
return response;
}
}
}
client.get("/some/relative/path")
.onSuccess(response -@gt; System.out.println("Success:" + res.toString()))
.onFailure(response -@gt; System.out.println("Failure:" + res.toString()))
.onResponse(response -@gt; System.out.println(res.getStatus()));
//-- instead of using the success/failure callbacks as above
//-- you can wait for the async process to complete by calling 'get()'
FutureResponse future = client.post("/some/relative/path", new JSNode("hello", "world"));
//-- request is asynchronously executing here
//-- the call to get() blocks indefinitely until the async execution completes
//-- the fact that this method is called 'get()' is not related to HTTP get.
Response response = future.get();
//-- now do whatever you want with the Response
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classAn asynchronous thread pool task runner.classA RunnableFuture that blocks on get() until the execution of the Request has returned the Response.static interface -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected intIfuseCompressionis true, anything over this size in bytes will be compressed.protected intParameter for default HttpClient configurationprotected final SetNever forward these headers.Never forward these params.protected RestClient.ExecutorThe thread pool executor used to make asynchronous requestsHeaders that are always sent regardless offorwardHeaders,includeForwardHeadersandexcludeForwardHeadersstate.protected booleanIndicates the headers from the root inbound Request being handled on this Chain should be included on this request minus anyexcludeForwardHeaders.protected booleanIndicates the params from the root inbound Request being handled on this Chain should be included on this request minus any blacklisted params.protected org.apache.http.client.HttpClientThe underlying HttpClient use for all network comms.protected final SetAlways forward these headers.Always forward these params.protected StringThe RestClient name that will be for property decoding.protected final List<RestClient.RequestListener>protected intParameter for default HttpClient configurationprotected intThe default maximum number of times to retry a requestprotected intThe maximum amount of time to wait before a single retry.protected intThe length of time before the first retry.protected intParameter for default HttpClient configurationprotected intThe number of background executor threads.protected StringOptional base url that will be prepended to the url arg of any calls assuming that the url arg supplied is a relative path and not an absolute url.protected booleanIndicates that a request body should be gzipped and the content-encoding header should be sent with value "gzip". -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected RestClient.ExecutorBuild an executor if one was not wired in.protected org.apache.http.client.HttpClientFactory method for building an HttpClient if one was not configured via withHttpClient.buildRequest(String method, String fullUrlOrRelativePath, Map<String, String> params, JSNode body, org.apache.commons.collections4.multimap.ArrayListValuedHashMap<String, String> headers, int retryMax) Builds a request with the supplied information merged with the url, query param, and header options configured on this reset client and potentially pulled from the Chain request.Executes the request as provided without modification.call(String method, String fullUrlOrRelativePath, Map<String, String> params, JSNode body, int retryMax, org.apache.commons.collections4.multimap.ArrayListValuedHashMap<String, String> headers) Makes an HTTP request.protected longcomputeTimeout(Request request, Response response) Computes an incremental retry backoff time between retryTimeoutMin and retryTimeoutMax.Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a DELETE request.protected ResponseThe work of executing the remote call is done here.Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.intintprotected org.apache.http.client.HttpClientgetName()intintintgetRetryTimeoutMax(int retryTimeoutMax) intintintbooleanbooleanbooleanonRequest(RestClient.RequestListener requestListener) onResponse(Consumer<Response> responseListener) Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a PATCH request.Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a POST request.Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a PUT request.removeExcludeForwardHeader(String headerKey) removeExcludeParam(String param) removeIncludeForwardHeader(String headerKey) removeIncludeParam(String param) protected booleanshouldForwardHeader(String headerKey) protected booleanshouldForwardParam(String param) protected booleanshouldRetry(Request request, Response response) Determines if the Request should be retried.withCompressionMinSize(int compressionMinSize) withConnectTimeout(int connectTimeout) withExcludeForwardHeaders(String... headerKeys) withExcludeParams(String... paramNames) withExecutor(RestClient.Executor executor) withForcedHeader(String name, String value) withForcedHeaders(String... headers) withForwardedHeaders(boolean forwardHeaders) withForwardedParams(boolean forwardParams) withForwardHeaders(boolean forwardHeaders) withForwardParams(boolean forwardParams) withHttpClient(org.apache.http.client.HttpClient httpClient) withIncludeForwardHeaders(String... headerKeys) withIncludeParams(String... paramNames) withRequestTimeout(int requestTimeout) withRetryMax(int retryMax) withRetryTimeoutMin(int retryTimeoutMin) withSocketTimeout(int socketTimeout) withThreadsMax(int threadsMax) withUseCompression(boolean useCompression) withWhitelistedHeaders(String... headerKeys) Deprecated.
-
Field Details
-
includeForwardHeaders
Always forward these headers. -
excludeForwardHeaders
Never forward these headers.- See Also:
-
forcedHeaders
protected final org.apache.commons.collections4.multimap.ArrayListValuedHashMap<String,String> forcedHeadersHeaders that are always sent regardless offorwardHeaders,includeForwardHeadersandexcludeForwardHeadersstate.These headers will overwrite any caller supplied or forwarded header with the same key, not append to the value list.
This list is initially empty.
-
includeParams
Always forward these params.- See Also:
-
excludeParams
Never forward these params.- See Also:
-
requestListeners
-
responseListeners
-
name
The RestClient name that will be for property decoding.- See Also:
-
forwardHeaders
protected boolean forwardHeadersIndicates the headers from the root inbound Request being handled on this Chain should be included on this request minus anyexcludeForwardHeaders.Default value is true.
-
url
Optional base url that will be prepended to the url arg of any calls assuming that the url arg supplied is a relative path and not an absolute url. -
useCompression
protected boolean useCompressionIndicates that a request body should be gzipped and the content-encoding header should be sent with value "gzip".Default value is true.
-
compressionMinSize
protected int compressionMinSizeIfuseCompressionis true, anything over this size in bytes will be compressed.Default value is 1024.
-
forwardParams
protected boolean forwardParamsIndicates the params from the root inbound Request being handled on this Chain should be included on this request minus any blacklisted params. -
executor
The thread pool executor used to make asynchronous requests -
retryMax
protected int retryMaxThe default maximum number of times to retry a requestThe default value is zero meaning by default, failed requests will not be retried
-
retryTimeoutMin
protected int retryTimeoutMinThe length of time before the first retry.Incremental retries receive progressively more of a timeout up to
retryTimeoutMax.- See Also:
-
retryTimeoutMax
protected int retryTimeoutMaxThe maximum amount of time to wait before a single retry.- See Also:
-
socketTimeout
protected int socketTimeoutParameter for default HttpClient configuration- See Also:
-
RequestConfig.Builder.setSocketTimeout(int)
-
connectTimeout
protected int connectTimeoutParameter for default HttpClient configuration- See Also:
-
RequestConfig.Builder.setConnectTimeout(int)
-
requestTimeout
protected int requestTimeoutParameter for default HttpClient configuration- See Also:
-
RequestConfig.Builder.setConnectionRequestTimeout(int)
-
httpClient
protected org.apache.http.client.HttpClient httpClientThe underlying HttpClient use for all network comms. -
threadsMax
protected int threadsMaxThe number of background executor threads.A value < 1 will cause all tasks to execute synchronously on the calling thread meaning the FutureResponse will always be complete upon return.
The default value is 5.
-
-
Constructor Details
-
RestClient
public RestClient() -
RestClient
- Parameters:
name- the prefix used to look up property values from the environment if they have not already been wired
-
-
Method Details
-
get
Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if set, can have a query string or not- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
get
Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if set, can have a query string or notqueryString- additional query string params in name=value@amp;name2=value2 style- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
get
Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if set, can have a query string or notparams- query strings passed in as a map- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
get
public RestClient.FutureResponse get(String fullUrlOrRelativePath, String... queryStringNameValuePairs) Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a GET request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if set, can have a query string or notqueryStringNameValuePairs- additional query string name/value pairs- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
post
Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a POST request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if setbody- the optional JSON to post- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
put
Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a PUT request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if setbody- the optional JSON to put- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
patch
Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a PATCH request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if setbody- the optional JSON patch- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
delete
Convenience overloading ofcall(String, String, Map, JSNode, int, ArrayListValuedHashMap)to perform a DELETE request.- Parameters:
fullUrlOrRelativePath- may be a full url or relative to theurlproperty if set- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
call
public RestClient.FutureResponse call(String method, String fullUrlOrRelativePath, Map<String, String> params, JSNode body, int retryMax, org.apache.commons.collections4.multimap.ArrayListValuedHashMap<String, String> headers) Makes an HTTP request.- Parameters:
method- the HTTP method to invokefullUrlOrRelativePath- optional may be a full url or only additional relative path parts if theurlproperty if set, may contain a query stringparams- optional additional query string params that will overwrite any that may be on url as composed frombuildUrl(String)body- optional json bodyretryMax- how many times the client should retry if the Request is not successful, if less than zero then this.retriesMax is usedheaders- headers that will always be sent regardless ofincludeForwardHeaders,excludeForwardHeadersbut may be overwritten byforcedHeaders- Returns:
- a FutureResponse that will asynchronously resolve to a Response
-
call
Executes the request as provided without modification.All of the other 'get/post/put/patch/delete/call' methods will construct a Request based on the configured properties of this RestClient and optionally the data in Request on the top of the Chain if operating inside an Engine.
Those methods ultimately delegate to this method and no further modification of the Request is made from here out.
- Parameters:
request-- Returns:
-
buildRequest
public Request buildRequest(String method, String fullUrlOrRelativePath, Map<String, String> params, JSNode body, org.apache.commons.collections4.multimap.ArrayListValuedHashMap<String, String> headers, int retryMax) Builds a request with the supplied information merged with the url, query param, and header options configured on this reset client and potentially pulled from the Chain request.- Parameters:
method- - the http methodfullUrlOrRelativePath- - a full url or a relative path that will be appended to this.urlparams- - query params to passbody- - the request body to passheaders- - request headers to passretryMax- - the number of times to retry this call if it fails.- Returns:
- the configure request
-
doRequest
The work of executing the remote call is done here.Override this method to intercept the remote call and change anything about the Request or Response that you want.
All of the Request url/header/param configuration has already been done on the Request.
You don't need to do anything related to threading here. This method is already executing asynchronously within the Executor's thread pool. Simply handle/transform the Request/Response as desired. Simply returning a Response will cause the FutureResponse to transition to done and allow calls blocking on FutureResponse.get() to receive the Response.
Overriding this method can be really helpful when you what your RestClient calling algorithm to say clean, hiding some of the Request/Response customization details or otherwise need to make sure Requests/Responses are always handled in a specific way.
A typical override of this method might look like the following:
protected RestClient client = new RestClient("myservice"){ protected Response doRequest(Request request) { if(checkMyCondition(request)) { //-- short circuit the remote call "faking" a //-- remote 200 response (the default status code for a Response) return new Response(request.getUrl()); } else { doMyRequestTransformation(request); Response response = super.getResponse(request); doMyResponseTransformation(response); return response; } } }- Parameters:
request- the request to make- Returns:
- a Response containing the server response data or error data. Will not be null.
-
onRequest
-
onResponse
-
computeTimeout
Computes an incremental retry backoff time between retryTimeoutMin and retryTimeoutMax.You can override this to provide your own timeout policy.
- Parameters:
request- the Request being maderesponse- the Response being computed- Returns:
- the number of milliseconds to wait before retrying the Request
-
shouldRetry
Determines if the Request should be retried.You can override this to provide your own retry policy.
The default algorithm will only retry if the Request is not successful due to a network error and the current request.retryCount is less than reqest.retryMax.
- Parameters:
request- the Request being maderesponse- the Response being computed- Returns:
- true if this request should be retried
- See Also:
-
isNetworkException(Throwable)
-
buildHttpClient
Factory method for building an HttpClient if one was not configured via withHttpClient.The default HttpClient constructed here basically SSL cert and hostname verification assuming that you will be calling clients you control.
If you need to adopt a tighter security posture just override this method or call
withHttpClient(HttpClient)to supply your own HttpClient and security configuration.Use of this method is wrapped by getHttpClient() which controls concurrency so this method should not be called more than once per instance if an error is not thrown.
- Returns:
- an HttpClient that can be use to make concurrent asynchronous requests.
- Throws:
Exception- if HttpClient construction fails- See Also:
-
withUrl
-
getForcedHeaders
-
withForcedHeader
-
withForcedHeaders
-
withForwardedHeaders
-
withForwardedParams
-
getName
-
withName
-
isUseCompression
public boolean isUseCompression() -
withUseCompression
-
getCompressionMinSize
public int getCompressionMinSize() -
withCompressionMinSize
-
getRetryMax
public int getRetryMax() -
withRetryMax
-
getSocketTimeout
public int getSocketTimeout() -
withSocketTimeout
-
getConnectTimeout
public int getConnectTimeout() -
withConnectTimeout
-
getRequestTimeout
public int getRequestTimeout() -
withRequestTimeout
-
withHttpClient
-
getHttpClient
protected org.apache.http.client.HttpClient getHttpClient() -
getExecutor
- Returns:
- lazy constructs
executorif necessary.
-
withExecutor
-
buildExecutor
Build an executor if one was not wired in.You can dependency inject your Executor or override this method to provide advanced customizations.
As a convenience RestClient.threadsMax is configured on the default executor.
- Returns:
- a default new Executor.
-
isForwardHeaders
public boolean isForwardHeaders() -
shouldForwardHeader
-
withForwardHeaders
-
getIncludeForwardHeaders
-
withIncludeForwardHeaders
-
withWhitelistedHeaders
Deprecated.Replaced bygetIncludeForwardHeaders() -
removeIncludeForwardHeader
-
getExcludeForwardHeaders
-
withExcludeForwardHeaders
-
removeExcludeForwardHeader
-
isForwardParams
public boolean isForwardParams() -
shouldForwardParam
-
withForwardParams
-
getIncludeParams
-
withIncludeParams
-
removeIncludeParam
-
getExcludeParams
-
withExcludeParams
-
removeExcludeParam
-
getRetryTimeoutMin
public int getRetryTimeoutMin() -
withRetryTimeoutMin
-
getRetryTimeoutMax
public int getRetryTimeoutMax() -
getRetryTimeoutMax
-
getThreadsMax
public int getThreadsMax() -
withThreadsMax
-
getIncludeForwardHeaders()