Class ApiClient
ApiClient gives you easy or built in:
- request response listeners that operate on all requests/responses. See ApiClient.withRequestListener()/.withResponseListener()
- fluent asynchronous response handler api on FutureResponse for response specific handling. See FutureResponse.onResponse()/onSuccess()/onFailure()
- header forwarding w/ whitelists and blacklists
- url query string param forwarding w/ whitelist and blacklists
- lazy runtime host url construction through lookup of "{ApiClient.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).
- change any request/response in an always thread safe way by overriding
doRequest(Request)
Intercepting and transforming requests and responses examples:
ApiClient client = new ApiClient().withRequestListener(req -> return new Response())//-- edit the request or return your own response to short circuits the remote call
.withResponseListener(res -> res.setStatus(200))//-- edit anything you want about the response
//-- you can also override "doRequest" to control everything before and after the actual HttpClient call.
client = new ApiClient("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.doRequest(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 JSMap("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 intParameter for default HttpClient configurationbooleanParameter for default HttpClient configurationintParameter for default HttpClient configurationprotected final SetNever forward these headers.Never forward these params.protected ApiClient.ExecutorThe thread pool executor used to make asynchronous requests.Headers 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 anyexcludeParams.protected org.apache.http.client.HttpClientprotected org.apache.http.impl.client.HttpClientBuilderprotected final SetForward these headers when forwardHeaders is true.Forward these params when forwardParams is true.intParameter for default HttpClient configurationintParameter for default HttpClient configurationprotected longResponses over this size will be written to a temp file that will be deleted when the Response inputStream is closed (or Response is finalized which closes the stream)protected StringThe ApiClient name that will be used for property decoding.protected final List<ApiClient.RequestListener>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 TypeMethodDescriptionorg.apache.http.impl.client.HttpClientBuilderprotected ApiClient.ExecutorBuild an executor if one was not wired in.protected org.apache.http.client.HttpClientbuildHttpClient(org.apache.http.impl.client.HttpClientBuilder builder) io.inversion.RequestbuildRequest(String method, String fullUrlOrRelativePath, Map<String, String> params, Object body, io.inversion.utils.ListMap<String, String> headers) 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.first() root caller request.call(io.inversion.Request request) Executes the Request as provided without modification ignoring forwardHeaders/forwardParams etc.call(String method, String fullUrlOrRelativePath, Map<String, String> params, Object body, io.inversion.utils.ListMap<String, String> headers) Makes an HTTP request.Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a DELETE request.protected io.inversion.ResponsedoRequest(io.inversion.Request request) The work of executing the remote call is done here.Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a GET request.Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a GET request.Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a GET request.Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a GET request.intintintintorg.apache.http.client.HttpClientorg.apache.http.impl.client.HttpClientBuilderintintlonggetName()intintbooleanbooleanbooleanbooleanonRequest(ApiClient.RequestListener requestListener) Requests listeners can modify the Request.onResponse(Consumer<io.inversion.Response> responseListener) Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a PATCH request.Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a POST request.Convenience overloading ofcall(String, String, Map, Object, ListMap)to perform a PUT request.removeExcludeForwardHeader(String headerKey) removeExcludeParam(String param) removeIncludeForwardHeader(String headerKey) removeIncludeParam(String param) replaceVars(io.inversion.Request parentRequest, String url) Replaces path parameters with their corresponding request paramsprotected booleanshouldForwardHeader(String headerKey) protected booleanshouldForwardParam(String param) withCompressionMinSize(int compressionMinSize) withConnectionRequestTimeout(int connectionRequestTimeout) withConnectTimeout(int connectTimeout) withEvictExpiredConnections(boolean evictExpiredConnections) withEvictIdleConnectionsAfterTimeMillis(int evictIdleConnectionsAfterTimeMillis) withExcludeForwardHeaders(String... headerKeys) withExcludeParams(String... paramNames) withExecutor(ApiClient.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) withHttpClientBuilder(org.apache.http.impl.client.HttpClientBuilder httpClientBuilder) withIncludeForwardHeaders(String... headerKeys) withIncludeParams(String... paramNames) withMaxConPerRoute(int maxConPerRoute) withMaxConTotal(int maxConTotal) withMaxMemoryBuffer(long maxMemoryBuffer) withSocketTimeout(int socketTimeout) withThreadsMax(int threadsMax) withUseCompression(boolean useCompression)
-
Field Details
-
forcedHeaders
Headers that are always sent regardless offorwardHeaders,includeForwardHeadersandexcludeForwardHeadersstate.These headers will overwrite any caller supplied or forwarded header with the same key, not simply appending to the value list.
This list is initially empty.
-
requestListeners
-
responseListeners
-
name
The ApiClient name that will be used for property decoding.- See Also:
-
Context
-
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. Any {paramName} variables will be replaced with with values from the current Request Url. -
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.
-
includeForwardHeaders
Forward these headers when forwardHeaders is true. -
excludeForwardHeaders
Never forward these headers.- See Also:
-
forwardParams
protected boolean forwardParamsIndicates the params from the root inbound Request being handled on this Chain should be included on this request minus anyexcludeParams.Default value is false.
-
includeParams
Forward these params when forwardParams is true.- See Also:
-
excludeParams
Never forward these params. Contains ["explain"] by default.- See Also:
-
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.
-
maxMemoryBuffer
protected long maxMemoryBufferResponses over this size will be written to a temp file that will be deleted when the Response inputStream is closed (or Response is finalized which closes the stream) -
executor
The thread pool executor used to make asynchronous requests. The Executor will expand tothreadsMaxworker threads. -
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 0.
-
socketTimeout
protected int socketTimeoutParameter for default HttpClient configurationDefault value is 30000ms
- See Also:
-
RequestConfig.Builder.setSocketTimeout(int)
-
connectTimeout
protected int connectTimeoutParameter for default HttpClient configurationDefault value is 30000ms
- See Also:
-
RequestConfig.Builder.setConnectTimeout(int)
-
connectionRequestTimeout
protected int connectionRequestTimeoutParameter for default HttpClient configurationDefault value is 30000ms
- See Also:
-
RequestConfig.Builder.setConnectionRequestTimeout(int)
-
maxConPerRoute
public int maxConPerRouteParameter for default HttpClient configurationDefault value is 10
- See Also:
-
HttpClientBuilder.setMaxConnPerRoute(int)
-
maxConTotal
public int maxConTotalParameter for default HttpClient configurationDefault value is 50ms
- See Also:
-
HttpClientBuilder.setMaxConnTotal(int)
-
evictExpiredConnections
public boolean evictExpiredConnectionsParameter for default HttpClient configuration- See Also:
-
HttpClientBuilder.evictExpiredConnections()
-
evictIdleConnectionsAfterTimeMillis
public int evictIdleConnectionsAfterTimeMillisParameter for default HttpClient configuration- See Also:
-
HttpClientBuilder.evictIdleConnections(long, TimeUnit)
-
httpClientBuilder
protected org.apache.http.impl.client.HttpClientBuilder httpClientBuilder -
httpClient
protected org.apache.http.client.HttpClient httpClient
-
-
Constructor Details
-
ApiClient
public ApiClient() -
ApiClient
- 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, Object, ListMap)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, Object, ListMap)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, Object, ListMap)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 ApiClient.FutureResponse get(String fullUrlOrRelativePath, String... queryStringNameValuePairs) Convenience overloading ofcall(String, String, Map, Object, ListMap)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, Object, ListMap)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, Object, ListMap)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, Object, ListMap)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, Object, ListMap)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 ApiClient.FutureResponse call(String method, String fullUrlOrRelativePath, Map<String, String> params, Object body, io.inversion.utils.ListMap<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 bodyheaders- 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 ignoring forwardHeaders/forwardParams etc.All of the other 'get/post/put/patch/delete/call' methods will use buildRequest() to construct a Request based on the configured properties of this ApiClient 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 io.inversion.Request buildRequest(String method, String fullUrlOrRelativePath, Map<String, String> params, Object body, io.inversion.utils.ListMap<String, String> headers) 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.first() root caller 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 pass- Returns:
- the configure request
-
doRequest
protected io.inversion.Response doRequest(io.inversion.Request request) 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 ApiClient 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 ApiClient client = new ApiClient("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.doRequest(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
Requests listeners can modify the Request. If they return null, request processing/execution will continue. If they return a Response, no additional RequestListeners will be notified and the supplied Response will be used instead of actually making the remote response. In this case all response listeners on this class or the FutureResponse will still be notified.- Parameters:
requestListener-- Returns:
-
onResponse
-
replaceVars
Replaces path parameters with their corresponding request params -
withUrl
-
getForcedHeaders
-
withForcedHeader
-
withForcedHeaders
-
withForwardedHeaders
-
withForwardedParams
-
getName
-
withName
-
isUseCompression
public boolean isUseCompression() -
withUseCompression
-
getCompressionMinSize
public int getCompressionMinSize() -
withCompressionMinSize
-
withHttpClient
-
getSocketTimeout
public int getSocketTimeout() -
withSocketTimeout
-
getConnectTimeout
public int getConnectTimeout() -
withConnectTimeout
-
getConnectionRequestTimeout
public int getConnectionRequestTimeout() -
withConnectionRequestTimeout
-
getMaxConPerRoute
public int getMaxConPerRoute() -
withMaxConPerRoute
-
getMaxConTotal
public int getMaxConTotal() -
withMaxConTotal
-
isEvictExpiredConnections
public boolean isEvictExpiredConnections() -
withEvictExpiredConnections
-
getEvictIdleConnectionsAfterTimeMillis
public int getEvictIdleConnectionsAfterTimeMillis() -
withEvictIdleConnectionsAfterTimeMillis
-
getHttpClient
public org.apache.http.client.HttpClient getHttpClient() -
buildHttpClient
protected org.apache.http.client.HttpClient buildHttpClient(org.apache.http.impl.client.HttpClientBuilder builder) throws Exception - Throws:
Exception
-
withHttpClientBuilder
public ApiClient withHttpClientBuilder(org.apache.http.impl.client.HttpClientBuilder httpClientBuilder) -
getHttpClientBuilder
public org.apache.http.impl.client.HttpClientBuilder getHttpClientBuilder() -
buildDefaultHttpClientBuilder
public org.apache.http.impl.client.HttpClientBuilder buildDefaultHttpClientBuilder() -
withExecutor
-
getExecutor
- Returns:
- lazy constructs
executorif necessary.
-
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 ApiClient.threadsMax is configured on the default executor.
- Returns:
- a default new Executor.
-
isForwardHeaders
public boolean isForwardHeaders() -
shouldForwardHeader
-
withForwardHeaders
-
getIncludeForwardHeaders
-
withIncludeForwardHeaders
-
removeIncludeForwardHeader
-
getExcludeForwardHeaders
-
withExcludeForwardHeaders
-
removeExcludeForwardHeader
-
isForwardParams
public boolean isForwardParams() -
shouldForwardParam
-
withForwardParams
-
getIncludeParams
-
withIncludeParams
-
removeIncludeParam
-
getExcludeParams
-
withExcludeParams
-
removeExcludeParam
-
getMaxMemoryBuffer
public long getMaxMemoryBuffer() -
withMaxMemoryBuffer
-
getThreadsMax
public int getThreadsMax() -
withThreadsMax
-