Using HTTPClientParams for HttpClient 4.5 - httpclient

I have a code with HttpClient 3.x which uses HTTPClientParams.
HttpClientParams params = new HttpClientParams();
params.setVersion(HttpVersion.HTTP_1_1);
params.setContentCharset(ENCODING);
try {
URI uri = new URI(some-resource);
int port = uri.getPort();
Protocol protocol = null;
if(port == -1){
if(uri.getScheme().compareToIgnoreCase("http") == 0){
port = 80;
protocol = Protocol.getProtocol("http");
}
else if(uri.getScheme().compareToIgnoreCase("https") == 0){
port = 443;
protocol = Protocol.getProtocol("https");
}
}
Protocol.registerProtocol(uri.getScheme(), protocol);
HttpConnectionManager manager = new SimpleHttpConnectionManager();
HttpClient client = new HttpClient(manager);
client.setParams(params);
I have verified that for HTTPClient 4.5 there are not HTTPParam method. How can I upgrade the same? Are there any alternatives?

Please have a look at RequestConfig class
This code should be roughly equivalent to your code above
CloseableHttpClient client = HttpClientBuilder.create()
.setConnectionManager(new BasicHttpClientConnectionManager())
.setDefaultRequestConfig(RequestConfig
.custom()
// Add custom request parameters
.build())
.build();
URI uri = new URI(some - resource);
HttpGet httpGet = new HttpGet(uri);
httpGet.setProtocolVersion(HttpVersion.HTTP_1_1);
try (CloseableHttpResponse response1 = client.execute(httpGet)) {
EntityUtils.toString(response1.getEntity(), Charset.forName(ENCODING));
}

Related

Websphere App Server 7.0.0.43 - IBM Java 1.6, Apache Wink, Rest Client TLSv1.2

Recently upgraded websphere app server to TLSv1.2. Prior, with TLSv1, was able to interface with REST client using combination of javax.ws.rs, org.glassfish.jersey and javax.net.ssl. Wasn't able to get working once app server upgraded TLS. IBM instructed to apply Feature Pack Web 2.0 and interface with REST client using Apache Wink. Haven't been able to get this solution to work. Previously, Keystore and Truststore were set on SSLContext.
private static String getClient(String servicePath){
try {
javax.ws.rs.client.Client client = null;
org.glassfish.jersey.client.ClientConfig clientConfig = new org.glassfish.jersey.client.ClientConfig();
int readTimeOut = Integer.parseInt(commonProp.getProperty(READ_TIMEOUT));
int connTimeout = Integer.parseInt(commonProp.getProperty(CONNECTION_TIMEOUT));
clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connTimeout);
clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeOut);
org.glassfish.jersey.SslConfigurator sslConfig;
String trustStoreName = commonProp.getProperty(TRUSTSTORE_NAME);
File file1 = new File("\\"+PROJECT_FILE_DIR+ "/ISB"+trustStoreName.trim());
String keyStoreName = commonProp.getProperty(KEYSTORE_NAME);
File file2 = new File("\\"+PROJECT_FILE_DIR+ "/ISB"+keyStoreName.trim());
FileInputStream fis1 = new FileInputStream(file1);
FileInputStream fis2 = new FileInputStream(file2);
String trustStorePassword = commonProp.getProperty(TRUSTSTORE_PASSWORD);
String keyStorePassword = commonProp.getProperty(KETSTORE_PASSWORD);
sslConfig = org.glassfish.jersey.SslConfigurator.newInstance().trustStoreBytes(ByteStreams.toByteArray(fis1))
.trustStorePassword(trustStorePassword).keyStoreBytes(ByteStreams.toByteArray(fis2))
.keyPassword(keyStorePassword);
javax.net.ssl.SSLContext sslContext = sslConfig.createSSLContext();
client = javax.ws.rs.client.ClientBuilder.newBuilder().sslContext(sslContext).withConfig(clientConfig).build();
String url = commonProp.getProperty(ENDPOINT_URL)+servicePath;
Response response =
client.target(url)
.request(MediaType.APPLICATION_JSON)
.get();
String responseAsString = "";
if(response != null){
responseAsString = response.readEntity(String.class);
}
return responseAsString;
} catch (Throwable e) {
logger.severe(e.getMessage() + e.getLocalizedMessage());
e.printStackTrace();
throw new RuntimeException(e);
}
}
With Installed Feature Pack and use of JSSEHELPER, retrieved SSL alias
information from WAS. Seem to make client connection now, but still have
authentication issue
Blockquote
response statusCode: 200
called close()
called closeInternal(true)
WebContainer : 0, SEND TLSv1.2 ALERT: warning, description = close_notify
An attempt to authenticate with a client certificate failed. A valid client
certificate is required to make this connection.
Blockquote
Believe issue may be that previously the KEYSTORE and TRUSTSTORE information
was read from file. Whereas the JSSEHELPER is simply putting file name.
com.ibm.ssl.clientAuthenticationSupported = false
com.ibm.ssl.keyStoreClientAlias = isbgatewaytst
com.ibm.ssl.contextProvider = IBMJSSE2
com.ibm.ssl.trustStoreProvider = IBMJCE
com.ibm.ssl.protocol = TLSv1.2
com.ibm.ssl.keyStoreReadOnly = false
com.ibm.ssl.alias = ISBGatewaySSL
com.ibm.ssl.keyStoreCreateCMSStash = false
com.ibm.ssl.securityLevel = CUSTOM
com.ibm.ssl.trustStoreName = ISBGatewayTrust
com.ibm.ssl.configURLLoadedFrom = security.xml
com.ibm.ssl.trustStorePassword = ********
com.ibm.ssl.keyStoreUseForAcceleration = false
com.ibm.ssl.trustManager = PKIX
com.ibm.ssl.validationEnabled = false
com.ibm.ssl.trustStoreInitializeAtStartup = false
com.ibm.ssl.keyManager = IbmX509
com.ibm.ssl.keyStoreFileBased = true
com.ibm.ssl.keyStoreType = JKS
com.ibm.ssl.trustStoreFileBased = true
com.ibm.ssl.trustStoreCreateCMSStash = false
com.ibm.ssl.trustStoreScope = (cell):ESB_DEV
com.ibm.ssl.trustStore = E:/IBM/content/resources/dev_projectfiles_dir/ISB/isb-truststore.jks
com.ibm.ssl.keyStoreProvider = IBMJCE
com.ibm.ssl.enabledCipherSuites = SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256 SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256 SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA
com.ibm.ssl.daysBeforeExpireWarning = 60
com.ibm.ssl.keyStoreServerAlias = isbgatewaytst
com.ibm.ssl.clientAuthentication = false
com.ibm.ssl.keyStore = E:/IBM/content/resources/dev_projectfiles_dir/ISB/isb-keystore-tst.jks
com.ibm.ssl.trustStoreUseForAcceleration = false
com.ibm.ssl.trustStoreReadOnly = false
com.ibm.ssl.keyStoreScope = (cell):ESB_DEV
com.ibm.ssl.tokenEnabled = false
com.ibm.ssl.keyStoreName = ISBGatewayPrivatekey
com.ibm.ssl.keyStorePassword = ********
com.ibm.ssl.keyStoreInitializeAtStartup = false
com.ibm.ssl.trustStoreType = JKS
My issue is how to put the KEYSTORE and TRUSTSTORE information on the org.apache.wink.client.ClientConfig or else where, similar to previously setting the javax.net.ssl.SSLContext? Did set the WAS SSL alias information on the ClientConfig properties, but believe that is just adding the Store's file location which isn't of use for the REST Client.
public static String getPPLUResponseString(String servicePath) {
String responseAsString = "";
com.ibm.websphere.ssl.JSSEHelper jsseHelper = com.ibm.websphere.ssl.JSSEHelper.getInstance();
try {
Properties sslProps = null;
String alias = "ISBGatewaySSL";
sslProps = jsseHelper.getProperties(alias, getConnectionInfo(), null);
org.apache.wink.client.ClientConfig clientConfig = new org.apache.wink.client.ClientConfig();
clientConfig.readTimeout(Integer.parseInt(commonProp.getProperty(READ_TIMEOUT)));
clientConfig.connectTimeout(Integer.parseInt(commonProp.getProperty(CONNECTION_TIMEOUT)));
clientConfig.setProperties(sslProps);
Enumeration keys = clientConfig.getProperties().keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = (String) clientConfig.getProperties().get(key);
System.out.println(" clientConfig.getProperties(): " + key + ": " + value);
}
org.apache.wink.client.RestClient restClient = new org.apache.wink.client.RestClient(clientConfig);
String url = commonProp.getProperty(ENDPOINT_URL) + servicePath;
System.out.println(" url: " + url);
org.apache.wink.client.Resource restResource = restClient.resource(url);
System.out.println(" before client response");
org.apache.wink.client.ClientResponse clientResponse = restResource.accept(MediaType.APPLICATION_JSON_TYPE).get();
int statusCode = clientResponse.getStatusCode();
System.out.println(" response statusCode: " + statusCode);
String responseEntity = clientResponse.getEntity(String.class);
System.out.println(" responseEntity start: " + responseEntity);
System.out.println(" responseEntity end: ");
if (responseEntity != null) {
responseAsString = responseEntity;
}
} catch (com.ibm.websphere.ssl.SSLException e) {
System.out.println(" com.ibm.websphere.ssl.SSLException");
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return responseAsString;
}

proxy for the REST

I have a method in which sending XML(byte array) through REST. I set the global properties of a test proxy (CCProxy). In the application CCProxy log I have nothing. What did I do wrong?
url = "https://myurl/api/Storage/Init";
SSLContext sc = createSslContext();
Client client = ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier(new HostnameVerifier() {
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}).build();
System.setProperty("http.proxySet", "true");
System.setProperty("http.proxyHost", "192.168.11.64");
System.setProperty("http.proxyPort", "808");
System.setProperty("https.proxyHost", "192.168.11.64");
System.setProperty("https.proxyPort", "808");
// client.property("http.proxy.server.uri", "192.168.11.64");
// client.property("http.proxy.server.port", "808");
// client.property("https.proxy.server.uri", "192.168.11.64");
// client.property("https.proxy.server.port", "808");
javax.ws.rs.core.Response response = client.target(url).request(MediaType.APPLICATION_JSON)
.post(Entity.entity(doc, MediaType.APPLICATION_XML));
setting CCProxy
The second question, how to set the proxy only for a particular method? I tried something like this but it did not work.
client.property("http.proxy.server.uri", "192.168.11.64");
client.property("http.proxy.server.port", "808");
Update: After the changes as suggested by CWasp
final SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, (x509CertChain, authType) -> true).build();
HttpClient httpClient = HttpClientBuilder.create()
.setProxy(new HttpHost("192.168.11.64", 808))
.setDefaultCredentialsProvider(credProvider).setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy())
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.setSSLContext(sslContext)
.build();
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
client = new ResteasyClientBuilder().httpEngine(engine).build();
Try this if proxy authentication required
For Jersey 2.x:
ClientConfig config = new ClientConfig();
config.connectorProvider(new ApacheConnectorProvider());
config.property(ClientProperties.PROXY_URI, "http://" + PROXY_HOST + ":" + PROXY_PORT);
config.property(ClientProperties.PROXY_USERNAME, PROXY_USER);
config.property(ClientProperties.PROXY_PASSWORD, PROXY_PASS);
JerseyClient client = new JerseyClientBuilder()
.withConfig(config)
.build();
For Resteasy:
Credentials credentials = new UsernamePasswordCredentials(PROXY_USER, PROXY_PASS);
CredentialsProvider credProvider = new BasicCredentialsProvider();
credProvider.setCredentials(new AuthScope(PROXY_HOST, PROXY_PORT), credentials);
HttpClient httpClient = HttpClientBuilder.create()
.setProxy(new HttpHost(PROXY_HOST, PROXY_PORT))
.setDefaultCredentialsProvider(credProvider)
.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy())
.build();
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
ResteasyClient client = new ResteasyClientBuilder()
.httpEngine(engine)
.build();

C# WebApi HttpClient Unauthorized

I have an issue about webapi2 and Authorization.
If I call web api with the old .Net 2.0 client (WebClient) there are not problems and the code is here:
//old 2.0 client
using (WebClient oldClient = new WebClient())
{
oldClient.UseDefaultCredentials = true;
oldClient.Credentials = CredentialCache.DefaultCredentials;
oldClient.Headers[HttpRequestHeader.ContentType] = "application/json";
oldClient.Headers[HttpRequestHeader.Accept] = "application/json";
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
javaScriptSerializer.MaxJsonLength = 2147483644;
ASCIIEncoding encoding = new ASCIIEncoding();
string objectToSendJson = javaScriptSerializer.Serialize(objectToSend);
byte[] objectToSendByte = encoding.GetBytes(objectToSendJson);
byte[] serviceOutput = oldClient.UploadData(uri + actionController, "POST", objectToSendByte);
string jsonStr = Encoding.UTF8.GetString(serviceOutput);
toReturn = JsonConvert.DeserializeObject<T>(jsonStr);
return toReturn;
}
but if I use the new 4.5 HttpClient WebApi return me Unauthorized
and the code is here:
HttpClientHandler httpWebApiClienthandler = new HttpClientHandler
{
UseDefaultCredentials = true,
Credentials = CredentialCache.DefaultCredentials,
};
System.Net.Http.HttpClient newHttpClient = new System.Net.Http.HttpClient(httpWebApiClienthandler)
//new 4.5 client
JsonMediaTypeFormatter jsonFormatter = new JsonMediaTypeFormatter();
if (objectToSend == null)
throw new Exception("object to send is null");
HttpContent httpContent = new ObjectContent<object>(objectToSend, jsonFormatter);
httpContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
response = newHttpClient.PostAsync(actionController, httpContent).Result;
Any help is highly appreciated.

Will HttpGet headers override httpClient headers (Apache HttpClient)?

I want to set header at the HttpClient, since I want most of my service calls to have the default headers.
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(ApacheHttpClient.DEFAULT_CONNECTION_TIMEOUT)
.setSocketTimeout(ApacheHttpClient.DEFAULT_SOCKET_TIMEOUT).build();
httpClient = HttpClients.custom().setDefaultHeaders(getDefaultHeaderList()).setDefaultRequestConfig(requestConfig).setRetryHandler(new RetryHandler()).build();
However, I would like to replace the default headers, if required. I would be setting it as HttpGet header.
int cTimeout = (connTimeout == null) ? DEFAULT_CONNECTION_TIMEOUT : connTimeout;
int sTimeout = (socketTimeout == null) ? DEFAULT_SOCKET_TIMEOUT : socketTimeout;
httpGet.setConfig(RequestConfig.custom().setConnectTimeout(cTimeout).setSocketTimeout(sTimeout).build());
Would the HttpGet header override the headers set at the HttpClient?
Debugging the request, in org.apache.http.impl.client.InternalHttpClient.doExecute(HttpHost, HttpRequest, HttpContext) I can see that config which holds the timeouts is first obtained from the request and if it not set, the default is used:
RequestConfig config = null;
if (request instanceof Configurable) {
config = ((Configurable) request).getConfig();
}
if (config == null) {
final HttpParams params = request.getParams();
if (params instanceof HttpParamsNames) {
if (!((HttpParamsNames) params).getNames().isEmpty()) {
config = HttpClientParamConfig.getRequestConfig(params);
}
} else {
config = HttpClientParamConfig.getRequestConfig(params);
}
}
if (config != null) {
localcontext.setRequestConfig(config);
}
setupContext(localcontext);

cannot instantiate the type httpclient in android

Am getting an error with the following line of code
HttpClient Client= new HttpClient.
I have tried rewriting it as HttpClient Client= new DefaultHttpClient. but it solves the problem and creates a new error with other methods
.
Here is a glimpse of my code
protected static MDSResult doExecute(Context ctx, HttpMethod method){
HttpClient client = new HttpClient();
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(ctx);
MDSResult response = null;
// If there's a proxy enabled, use it.
String proxyHost = preferences.getString(
Constants.PREFERENCE_PROXY_HOST, "");
String sProxyPort = preferences.getString(
Constants.PREFERENCE_PROXY_PORT, "0");
boolean useSecure = preferences.getBoolean(
Constants.PREFERENCE_SECURE_TRANSMISSION, false);
int proxyPort = 0;
try {
if (!"".equals(sProxyPort))
proxyPort = Integer.parseInt(sProxyPort);
} catch(NumberFormatException e) {
Log.w(TAG, "Invalid proxy port: " + sProxyPort);
}
if (!"".equals(proxyHost) && proxyPort != 0) {
Log.i(TAG, "Setting proxy to " + proxyHost + ":" + proxyPort);
HostConfiguration hc = new HostConfiguration();
hc.setProxy(proxyHost, (int)proxyPort);
client.setHostConfiguration(hc);
}
// execute the Http/https method
try {
if(useSecure){
ProtocolSocketFactory ssl = new SimpleSSLProtocolSocketFactory();
Protocol https = new Protocol("https", ssl, 443);
Protocol.registerProtocol("https", https);
}
int status = client.executeMethod(method);
Log.d(TAG, "postResponses got response code " + status);
char buf[] = new char[20560];
Reader reader = new InputStreamReader(
method.getResponseBodyAsStream());
int total = reader.read(buf, 0, 20560);
String responseString = new String(buf);
Log.d(TAG, "Received from MDS:" + responseString.length()+" chars");
Gson gson = new Gson();
response = gson.fromJson(responseString, MDSResult.class);
}
You want DefaultHttpClient, not HttpClient like you mentioned. HttpClient is abstract so cannot be instantiated.
HttpClient client = new DefaultHttpClient();
What is the error with the other methods when you use that ?
Also why not use HttpURLConnection ? I find it much more reliable.