I don't know what I've done, so I'll write down what I changed.
** Supports major interface changes from Java apache HttpClient 4.3 (@mychaelstyle) ** https://qiita.com/mychaelstyle/items/e02b3011d1e71bfa26c5 ** Apache httpclient CloseableHttpClient to HTTPS site Request with BASIC authentication (@sh_kawakami) ** https://qiita.com/sh_kawakami/items/bf6d1397851cccd134b2 ** It seems that the interface of httpclient has changed significantly from 4.3 (@sakito) ** https://qiita.com/sakito/items/6366015dbbc4a88d56fc What does setDefaultMaxPerRoute and setMaxTotal mean in HttpClient? Answer column for https://stackoverflow.com/questions/30689995/what-does-setdefaultmaxperroute-and-setmaxtotal-mean-in-httpclient
JDK 1.8.162 httpclient 4.5.4
pom.xml
pom.xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.4</version>
</dependency>
I've been looking around like I've never been helped by the Deprecated List
―― 3.x series https://hc.apache.org/httpclient-3.x/apidocs/deprecated-list.html ―― 4.x series http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/deprecated-list.html
http://hc.apache.org/httpcomponents-client-ga/tutorial/html/index.html
Since it is a guide when raising from 3.x to 4.0, it may change again when it reaches 4.5. http://debuguide.blogspot.jp/2013/01/quick-guide-for-migration-of-commons.html
―― 3.x series https://hc.apache.org/httpclient-3.x/apidocs/constant-values.html ―― 4.x series http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/constant-values.html
before.java
HttpClient client = new HttpClient();
Let's use Builder! It seems that. If you don't have to think about anything, below.
after.java
HttpClient client = HttpClients.createDefault();
However, it may not be very practical because you have to pass the connection settings at the timing of generation.
GetMethod→HttpGet PostMethod→HttpPost Parent class HttpMethod → HttpRequestBase Change to
It used to be like this
before.java
PostMethod post = new PostMethod(url);
post.setRequestEntity(Set something);
int responseCode = client.executeMethod(post);
if (responseCode == 200) {
Reader reader = new InputStreamReader(
httpMethod.getResponseBodyAsStream(), httpMethod.getResponseCharSet());
//Subsequent processing
} else {
//Error handling
}
It's changed a lot and looks like this. But now that it's clear, it may be easier to understand.
after.java
HttpPost post = new HttpPost(url);
//Set the one that corresponds to the request body
post.setEntity(Set something);
HttpResponse response = client.execute(post);
StatusLine statusLine = response.getStatusLine();
int responseCode = statusLine.getStatusCode();
if (responseCode == HttpStatus.SC_OK) {
Reader reader = new InputStreamReader(
response.getEntity().getContent(), Charset.forName("UTF-8"));
//Subsequent processing
} else {
//Error handling
}
I used to do it like this.
before.java
Credentials credentials = new UsernamePasswordCredentials(this.username, this.password);
AuthScope scope = new AuthScope(host, port, this.realm);
client.getState().setCredentials(scope, credentials);
It seems that you should use CredentialsProvider. (Thanks to @sh_kawakami!)
after.java
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(baseUrl.getHost(),baseUrl.getPort()),
new UsernamePasswordCredentials(username, password));
//I will set it when creating an instance
HttpClient client = HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build();
It seems that the entity class is now BasicNameValuePair. It seems that it is just divided by "=", so I pray that the behavior will not change. But the setter is gone! !! !! It looks like it can only be set in the constructor. If you still want to use setter, you have to inherit NameValuePair and create your own class.
Let's add it ourselves
//host header
httpMethod.addHeader("Host", uri.getHost());
If there is a Content-Length header in the response, it will occur if the size is different from the Body. It doesn't happen without the Content-Length header (though it feels like an RFC violation) For example, it occurs when the response is like this. Well, today I think that Content-Length is calculated automatically and the server returns it without permission, so I think that it rarely occurs, but for various reasons I do not trust the response header: sweat:
HTTP/1.1 200 OK
Content-Type: text/html; charset=Shift_JIS
Content-Length: 3000
<html>
<head><title>Hoge</title>
</head>
<body>test
</body>
</html>
org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 3000; received: 124
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:178)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:135)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:148)
The cause is here
java:org.apache.http.impl.io.ContentLengthInputStream.java
/**
* Does standard {@link InputStream#read(byte[], int, int)} behavior, but
* also notifies the watcher when the contents have been consumed.
*
* @param b The byte array to fill.
* @param off Start filling at this position.
* @param len The number of bytes to attempt to read.
* @return The number of bytes read, or -1 if the end of content has been
* reached.
*
* @throws java.io.IOException Should an error occur on the wrapped stream.
*/
@Override
public int read (final byte[] b, final int off, final int len) throws java.io.IOException {
if (closed) {
throw new IOException("Attempted read from closed stream.");
}
if (pos >= contentLength) {
return -1;
}
int chunk = len;
if (pos + len > contentLength) {
chunk = (int) (contentLength - pos);
}
final int count = this.in.read(b, off, chunk);
if (count == -1 && pos < contentLength) {
throw new ConnectionClosedException(
"Premature end of Content-Length delimited message body (expected: "
+ contentLength + "; received: " + pos);
}
if (count > 0) {
pos += count;
}
return count;
}
I haven't found a solution so far.
javax.net.ssl.SSLPeerUnverifiedException: Certificate for <hostname> doesn't match any of the subject alternative names:
It seems that the host name is verified by default. The relevant part is here
java:org.apache.http.conn.ssl.SSLConnectionSocketFactory.java#verifyHostname
if (!this.hostnameVerifier.verify(hostname, session)) {
final Certificate[] certs = session.getPeerCertificates();
final X509Certificate x509 = (X509Certificate) certs[0];
final List<SubjectName> subjectAlts = DefaultHostnameVerifier.getSubjectAltNames(x509);
throw new SSLPeerUnverifiedException("Certificate for <" + hostname + "> doesn't match any " +
"of the subject alternative names: " + subjectAlts);
}
Since verify only needs to return true, it seems that an instance of the NoopHostnameVerifier class should be used. Disable SSL certificate verification and host name verification in Apache HttpComponents / Client Chapter 2. Connection management 2.7.4. Hostname verification In my case, I do not set SSLContext or SSLConnectionSocketFactory directly in httpclient, but implement it by setting it in ConnectionManager. At this point. So it looks like the following.
public static PoolingHttpClientConnectionManager createConnectionManager() {
SSLContext sslContext = null;
try {
sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy(){
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}
).build();
} catch (Exception e) {
e.printStackTrace();
}
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslsf)
.build();
return new PoolingHttpClientConnectionManager(registry);
}
Apache HttpClient DefaultHttpRequestRetryHandler does not retry on ConnectTimeoutException http://kntmr.hatenablog.com/entry/2016/12/09/150615 Use of non-ascii credentials not working in httpclient 4.3.x https://stackoverflow.com/questions/27955067/use-of-non-ascii-credentials-not-working-in-httpclient-4-3-x
Recommended Posts