-
Notifications
You must be signed in to change notification settings - Fork 13
HTTP Client
Foundation Communication supports a simple API that wraps standard HTTP client interactions. The idea behind the API is to supply an easy-to-use modern API that will enable working with multiple implementations. These can vary as long as they comply with the interfaces. Our current implementation are for latest Apache Client and Jetty Client.
Following is an explanation on how to use and configure the HTTP Client instance built by Foundation Infra.
The Main building blocks are:
- HttpClient - The basic interface. This is a thread safe object that can and should be re-used across your application.
- HttpClientFactory - The factory used to build the HTTP Client. Each implementation library will have it's own specific Factory class.
- HttpRequest - An immutable object that holds all request related data.
- HttpResponse - An object holding all the relevant response data.
The factory API has many overloads that enable you to set default load-balancing on/off flag (this affects you if you call the execute method), inject configuration other than that used by configuration-lib library and change the strategy type (by default ROUND_ROBIN will be used).
The client can be used with full uri in case of external LB with known VIP or just access to a static resource on the WAN. For this, call the executeDirect method or execute if in the factory you instructed the library to build a non LB client. Calling executeWithLoadBalancer will ensure full usage of client side LB.
Note: **For verifying you are closing and releasing connections back to the pool, if autoCloseable is set to false, you must either consume the entity payload (getResponseAsString, or getResponse) OR call the 'close' API on the response object.
If autoCloseable is true - it will sliently consumer the response content and cache it in the wrapping response object. If you need streaming you must disab;e the auto-close behavior and call close on the response manually in a finally block. **
You should acquire an instance by using the following code. Notice the usage of request uri instead of url:
HttpClient clientTest = ApacheHttpClientFactory.createHttpClient("muku");
HttpRequest request = HttpRequest.newBuilder()
.httpMethod(HttpMethod.GET)
.contentType("text/html")
.uri("/my/path/to/resource")
.header("H1","header 1 value 1")
.header("H1","header 1 value 2")
.header("H2","header 2 value")
.queryParams("hhid","1223479")
//.lbKey("") - optionally add a key to use with sticky servers
.build();
HttpResponse response = clientTest.executeWithLoadBalancer(request);
LOGGER.info(response.getResponseAsString());
You can also run an async request:
private static class MyResponseHandler implements ResponseCallback<ApacheHttpResponse>{
@Override
public void completed(ApacheHttpResponse response) {
String responseAsString = response.getResponseAsString();
LOGGER.info(responseAsString ); }
@Override
public void failed(Throwable e) {
LOGGER.error(e); }
@Override
public void cancelled() {
//not implemented }
}
HttpClient clientTest = ApacheHttpClientFactory.createHttpClient("clientTest", LoadBalancerStrategy.STRATEGY_TYPE.FAIL_OVER);
HttpRequest request = HttpRequest.newBuilder()
.httpMethod(HttpMethod.GET)
.uri("http://www.google.com")
.build();
clientTest.executeWithLoadBalancer(request, new MyResponseHandler());
The full set of parameters that you can use in the config.properties is listed here:
Key | Description |
---|---|
<apiName>.<index>.host | The host name of the server being invoked. |
<apiName>.<index>.port | The port the server is listening on. |
<apiName>.http.connectTimeout | The time (in millis) The time to wait before timeouting an attempt to establish a new connection Default value is: 5000. |
<apiName>.http.idleTimeout | The timeout (in millis) for idle connections. Default value is: 180000. |
<apiName>.http.maxConnectionsPerAddress | The maximum connections kept open per address (address is a server host:port pair). Default value is: 1000. |
<apiName>.http.maxQueueSizePerAddress | The maximum queue size of pending requests when all connections in the pool are currently used. Default value is: 1000. |
<apiName>.http.readTimeout | The time (in millis) to wait before request is time out in the client. Default value is: 5000. |
<apiName>.http.monitoringBaseUri |
A list of base Uri's. This list will be matched against the actual uri
being served. If a match is found the base Uri will be used as the
ApiName in monitoring of the server connections. It is recommended to
not use any RegEx in this context and provide uri prefixes only - you
should define the array like this:
|
<apiName>.http.numberOfAttempts | The number of times to try and call a server before it will be passivated. Each server will be called several times in case of a failure to be sure that it failed for something that was not random. Default value is: 3. |
<apiName>.http.retryDelay | The time (in millis) to wait between retries. In order to make sure that the server is not temporarily unstable or maybe failed due to a random reason we wait for X milliseconds and try again. It is advised to set a small number here (no more than 1000-5000 milliseconds). Default value is: 500. |
<apiName>.http.waitingTime | The time (in millis) to wait after a server was passivated before trying to activate it again. This parameter is very important. It is advised to set it for a long period of time. If a server passivated it means that it timed out for X times. This means it is something fatal. It is advised to set this value for at least 60000 milliseconds (1 minute). Default value is: 60000. |
<apiName>.http.exposeStatisticsToMonitor | When set to true client requests will be monitored. This key is used as is without the config prefix prefix. Default value is: true. |
<apiName>.http.autoCloseable | Set to true if you want the client to close automatically and release the connection even before consuming the content. Note: you may need to disable this and call close directly if you want to work with the inputstream using streaming style.Default value is: true. |
<apiName>.http.autoEncodeUri | Set to false if you want the client to not encode URI's automatically. It is the calling API responsability to pass in a fully encoded URI - including query params if such exist.Default value is: true. |
<apiName>.http.serviceDirectory.isEnabled | Set to true if you want the client to work with a Service Directory. If you have a server that meets the API published by the sd-api lib, you can enable it here. You can set host and port using Configuration, see service.sd.host and service.sd.port below. More info on sd-api.Default value is: false. |
<apiName>.http.serviceDirectory.serviceName | Set the service name for the service lookup. This value is set by the applicative server you want to access and should have the same value. |
<apiName>.http.staleConnectionCheckEnabled | Set to true if you want Client connections to be tested before re-used from the pool. Currently supported only in Apache client.Note: can have a performance hit of up to 30 milliseconds per request.Default value is: false. |
<apiName>.http.followRedirects | Set to true if you want the client to follow redirects automatically.Default value is: false. |
<apiName>.http.keyStorePath | For SSL support. Path to keystore file. |
<apiName>.http.keyStorePassword | For SSL support. Keystore file password. |
<apiName>.http.trustStorePath | For SSL support. Path to trust-store file. |
<apiName>.http.trustStorePassword | For SSL support. Trust-store file password. |
<apiName>.http.enforceTLS |
For SSL support. Set to true if an exception should be thrown if the client fails to support SSL.
Default value is: false |
service.sd.host | Set the host for a service directory server that implements the sd-api |
service.sd.port | Set the port for a service directory server that implements the sd-api |
<Parameter name="service.myHttpClient" base="service.http.client.base" description="my client description" type="STRUCTURE">
<DefaultValue>
<StructureValue>
<StructureMemberValue name="server">
<StructureValue index="1">
<StructureMemberValue name="host" value="<your http server host>" />
<StructureMemberValue name="port" value="<your http server port>" />
</StructureValue>
</StructureMemberValue>
</StructureValue>
</DefaultValue>
</Parameter>
This will take the structure member definition that the http server supports from the "service.http.base" base and add it to your specific http server definition. Now you only need to override any values you want (usually, you should at least override the port).
You can pass in the configuration a keystore path and password and truststore path and password. Doing so will enable client side ssl support. To enforce ssl support, set enforceTLS to true. Doing so will cause an exception to be thrown if ssl configuration fails.
We support automatic monitoring of ServerConnections.
In some cases you may want to use some specific Apache client features. One of these features could be a custom Apache client HttpEntity Object.
Regular Httprequest only support string or byte array payloads. If you need any other support (e.g. MultiPart), you can set a custom ApacheHttpRequest:
ApacheHttpRequest requestBuilder = ApacheHttpRequest.newBuilder();
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create()
HttpEntity httpEntity = multipartEntityBuilder.build()
ApacheHttpRequest httpRequest= requestBuilder
.uri("<your uri>")
.httpMethod(HttpMethod.POST)
.contentType("multipart/form-data")
.apacheEntity(httpEntity)
.build()