How do I get the cookies from Apache HttpClient 4.x? - httpclient

How do I get the cookies from an existing object of type HttpClient?
I'm using HttpClient version 4.3.3 which has no method httpClient.getCookieStore() anymore.

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpClientContext context = HttpClientContext.create();
CloseableHttpResponse response = httpclient.execute(new HttpGet("/"), context);
try {
CookieStore cookieStore = context.getCookieStore();
List<Cookie> cookies = cookieStore.getCookies();
} finally {
response.close();
}

version 4.5.2
You can use this code:
List<Cookie> cookies = ((CookieStore)localContext.getAttribute(HttpClientContext.COOKIE_STORE)).getCookies();

Related

Spring Boot Feign and Restemplate verify purchase order with Apple return error 21004

I have a Object Dto to verify purchase order with Apple.
String payload = "MIIT3w.....";
String password = "****";
AppleVerifyReceiptRequestCli requestCli= new AppleVerifyReceiptRequestCli();
receiptRequestCli.setReceiptData(payload);
receiptRequestCli.setPassword(password);
receiptRequestCli.setExcludeOldTransaction(false);
Using Restemplate :
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
// Call api to Apple Store to verify
String url = "https://buy.itunes.apple.com/verifyReceipt";
HttpEntity<AppleVerifyReceiptRequestCli> reqUpContentDTO = new HttpEntity<>(requestCli, headers);
HttpEntity<AppleVerifyReceiptResponseCli> responseCliHttpEntity = restTemplate.exchange(url, HttpMethod.POST,reqUpContentDTO, AppleVerifyReceiptResponseCli.class);
Receiver a right resposne {"environment":"Production","receipt":{"adam_id":"159579***" .....}
Using Feign :
#FeignClient(value = "IAppleFeign", url = "https://buy.itunes.apple.com")
public interface IAppleFeign {
#PostMapping(path = "/verifyReceipt",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<AppleVerifyReceiptResponseCli> verifyReceipt(
#RequestBody AppleVerifyReceiptRequestCli request);
}
Receive response error : {"environment":"Production","receipt":null,"status":21004}
I don't know, why Apple return 21004 with feign ?
Tell me why? please.

Using HTTPClientParams for HttpClient 4.5

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));
}

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.

HTTPClient unable to establish route between https and http

I am testing HttpClient 4.2 by hitting a mixture of http and https links.
HttpClient seems to stick with the protocol from the first call. If the first call is http, then all following https calls fail but http calls are fine. And vice versa.
Here is the test code I used.
#Test
public void testNoRedirectMixed() throws ClientProtocolException, IOException {
HttpClient httpclient = new DefaultHttpClient();
httpclient=WebClientDevWrapper.wrapClient(httpclient);
HttpClientParams.setRedirecting(httpclient.getParams(), false);
{
HttpGet httpget = new HttpGet("http://www.hotmail.com");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
assertTrue(EntityUtils.toString(entity).indexOf("com")>0);
}
try {
HttpGet httpget = new HttpGet("https://www.hotmail.com");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
}catch (Exception e) {
e.printStackTrace();
}
{
HttpGet httpget = new HttpGet("http://www.baidu.com");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
assertTrue(EntityUtils.toString(entity).indexOf("com")>0);
}
}
The second request (https) will fail, but the baidu request is fine.
Caused by: org.apache.http.HttpException: Unable to establish route: planned = {s}->https://www.hotmail.com; current = {s}->http://www.hotmail.com
at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:842)
I also have to disable redirection because hotmail redirects request: http://www.hotmail.com -> https://www.hotmail.com or https://www.hotmail.com -> https://www.live.com. A similar error is thrown in either cases.
The wrapper is shown below. It is used to accept all certificates.
public class WebClientDevWrapper {
public static HttpClient wrapClient(HttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs,
String string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", ssf, 443));
DefaultHttpClient client= new DefaultHttpClient(ccm, base.getParams());
return client;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}
HttpClient should be able to manage connections absolutely transparently to the user. This problem is likely to be caused by a regression introduced in the 4.2 release (see HTTPCLIENT-1193).
Use either PoolingConnectionManager or SingleConnectionManager instead of the default one until 4.2.1 version is released.
You are trying to use one connection to communicate to a number of different sites. AFAIR You have to create new connection (== new client) for every unique site.