Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpAsyncClient: Update to version 5.0.3. #196

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libraries.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ ext {
restAssuredVersion = '2.9.0'
vaadinVersion = '8.11.2'
nettyVersion = '4.1.42.Final'
httpAsyncClientVersion = '4.1.4'
httpClientVersion = '5.0.3'
mysqlJDBCVersion = '8.0.17'
c3p0Version = '0.9.5.4'
postgresJDBCVersion = '42.2.11'
Expand Down Expand Up @@ -127,7 +127,7 @@ ext {

jsonSchemaValidator: "com.github.java-json-tools:json-schema-validator:${jsonSchemaVersion}",
guava: "com.google.guava:guava:${guavaVersion}",
httpAsyncClient: "org.apache.httpcomponents:httpasyncclient:${httpAsyncClientVersion}",
httpAsyncClient: "org.apache.httpcomponents.client5:httpclient5:${httpClientVersion}",
flywaydb: "org.flywaydb:flyway-core:${flywaydbVersion}",
liquibase: "org.liquibase:liquibase-core:${liquibaseVersion}",

Expand Down
2 changes: 1 addition & 1 deletion modules/http-client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ description = 'jPOS-EE :: QRest Client'

dependencies {
api libraries.jpos
api libraries.httpAsyncClient
implementation libraries.httpAsyncClient
testImplementation project(':modules:qrest')
}

Expand Down
121 changes: 62 additions & 59 deletions modules/http-client/src/main/java/org/jpos/http/client/HttpQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,40 @@
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.security.cert.CertificateExpiredException;

import org.apache.http.*;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.AuthCache;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustAllStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.auth.*;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.auth.BasicAuthCache;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.auth.BasicScheme;
import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.client5.http.protocol.RedirectStrategy;
import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.message.StatusLine;
import org.jpos.core.ConfigurationException;
import org.jpos.transaction.AbortParticipant;
import org.jpos.util.Destroyable;
Expand Down Expand Up @@ -115,25 +108,33 @@ public HttpQuery () {
public int prepare (long id, Serializable o) {
Context ctx = (Context) o;

HttpRequestBase httpRequest = getHttpRequest(ctx);
SimpleHttpRequest httpRequest = getHttpRequest(ctx);
if (httpRequest == null)
return ignoreNullRequest ? PREPARED | NO_JOIN | READONLY : FAIL;

addHeaders(ctx, httpRequest);

httpRequest.setConfig(RequestConfig.custom().
setConnectTimeout(connectTimeout).
setSocketTimeout(timeout).
setConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS).
setResponseTimeout(timeout, TimeUnit.MILLISECONDS).
build());

HttpClientContext httpCtx= HttpClientContext.create(); // per-request http context

String basicAuth = ctx.get(basicAuthenticationName);
if (basicAuth != null && basicAuth.contains(":")) {
HttpHost host = null;
try {
URI uri = httpRequest.getUri();
host = new HttpHost(uri.getScheme(), uri.getHost(), uri.getPort());
} catch (URISyntaxException e) {
ctx.log(e);
}
String[] credentials = basicAuth.split(":");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(credentials[0], credentials[1]));
BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(host, null, StandardAuthScheme.BASIC),
new UsernamePasswordCredentials(credentials[0], credentials[1].toCharArray()));
httpCtx.setCredentialsProvider(credsProvider);

// NOTE: The Apache HTTP client does not do preemptive authentication out of the box.
Expand All @@ -143,29 +144,24 @@ public int prepare (long id, Serializable o) {
// For preemptive authentication, an AuthCache needs to be configured.
// Ref: https://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/authentication.html
if (preemptiveAuth) {
URI uri= httpRequest.getURI();
AuthCache authCache= new BasicAuthCache();
authCache.put(new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()), new BasicScheme());
authCache.put(host, new BasicScheme());
httpCtx.setAuthCache(authCache);
}
}

boolean trustAllCerts = ctx.getString(trustAllCertsName, "false").equals("true");
getHttpClient(trustAllCerts).execute(httpRequest, httpCtx, new FutureCallback<HttpResponse>() {
getHttpClient(trustAllCerts).execute(httpRequest, httpCtx, new FutureCallback<SimpleHttpResponse>() {
@Override
public void completed(HttpResponse result) {
ctx.log (result.getStatusLine());
public void completed(SimpleHttpResponse result) {
ctx.log (new StatusLine(result));

int sc = result.getStatusLine().getStatusCode();
int sc = result.getCode();

// we always include the response body on success and check responseOnError for failed requests
boolean includeResponse= (sc == HttpStatus.SC_CREATED) || (sc == HttpStatus.SC_OK) || responseOnError;
if (includeResponse) {
try {
ctx.put (responseName, EntityUtils.toString(result.getEntity()));
} catch (IOException e) {
ctx.log (e);
}
ctx.put (responseName, result.getBodyText());
}

ctx.put (statusName, sc); // status has to be the last entry because client might be waiting on it
Expand Down Expand Up @@ -242,7 +238,7 @@ public void setConfiguration (Configuration cfg) throws ConfigurationException {
if ("default".equals(redirProp))
redirectStrategy= DefaultRedirectStrategy.INSTANCE;
else if ("lax".equals(redirProp))
redirectStrategy= LaxRedirectStrategy.INSTANCE;
redirectStrategy= DefaultRedirectStrategy.INSTANCE;
else
throw new ConfigurationException("'redirect-strategy' must be 'lax' or 'default'");
}
Expand Down Expand Up @@ -298,7 +294,14 @@ public void checkServerTrusted(X509Certificate[] certs, String authType) {
try {
sc = SSLContext.getInstance("TLS");
sc.init(null, wrappedTrustManagers, new SecureRandom());
return builder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSSLContext(sc);
return builder.setConnectionManager(PoolingAsyncClientConnectionManagerBuilder
.create()
.setTlsStrategy(ClientTlsStrategyBuilder
.create()
.setHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.setSslContext(sc)
.build())
.build());
} catch (NoSuchAlgorithmException | KeyManagementException e) {
LogEvent evt = new LogEvent(this, "warn");
evt.addMessage(e);
Expand All @@ -319,24 +322,24 @@ private String getURL (Context ctx) {
return sb.toString();
}

private HttpRequestBase getHttpRequest(Context ctx) {
private SimpleHttpRequest getHttpRequest(Context ctx) {
String url = getURL(ctx);
String payload;
switch (ctx.getString(methodName)) {
case "POST":
HttpPost post = new HttpPost(url);
SimpleHttpRequest post = SimpleHttpRequests.post(url);
payload = ctx.getString(requestName);
if (payload != null)
post.setEntity(new StringEntity(payload, getContentType(ctx)));
post.setBody(payload, getContentType(ctx));
return post;
case "PUT":
HttpPut put = new HttpPut(url);
SimpleHttpRequest put = SimpleHttpRequests.put(url);
payload = ctx.getString(requestName);
if (payload != null)
put.setEntity(new StringEntity(payload, getContentType(ctx)));
put.setBody(payload, getContentType(ctx));
return put;
case "GET":
return new HttpGet(url);
return SimpleHttpRequests.get(url);
}
ctx.log ("Invalid request method");
return null;
Expand All @@ -345,11 +348,11 @@ private HttpRequestBase getHttpRequest(Context ctx) {
private ContentType getContentType (Context ctx) {
return cfg.getBoolean("no-charset") ?
ContentType.create(ctx.get(contentTypeName, contentType)) :
ContentType.create(ctx.get(contentTypeName, contentType), Consts.UTF_8);
ContentType.create(ctx.get(contentTypeName, contentType), StandardCharsets.UTF_8);
}

@SuppressWarnings("unchecked")
private void addHeaders(Context ctx, HttpUriRequest req) {
private void addHeaders(Context ctx, SimpleHttpRequest req) {
// first add the ones from the cfg
req.setHeaders(httpHeaders);

Expand Down Expand Up @@ -397,7 +400,7 @@ public void destroy() {
}

private CloseableHttpAsyncClient destroyClient (CloseableHttpAsyncClient client) {
if (client != null && client.isRunning()) {
if (client != null) {
try {
client.close();
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@

package org.jpos.http.client;

import org.apache.http.HttpStatus;
import org.apache.hc.core5.http.HttpStatus;
import org.jpos.iso.ISOUtil;
import org.jpos.q2.Q2;
import org.jpos.transaction.Context;
import org.jpos.transaction.TransactionManager;
import org.jpos.transaction.TransactionStatusEvent;
import org.jpos.transaction.TransactionStatusListener;
import org.jpos.util.NameRegistrar;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
Expand Down