Skip to content

Commit

Permalink
Add ability to set custom HostnameVerifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrei Kliuchnikau authored and Andrei Kliuchnikau committed Feb 28, 2024
1 parent 1f1f72d commit 6fa8c9e
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
20 changes: 20 additions & 0 deletions src/main/java/org/jsoup/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.jsoup.parser.StreamParser;
import org.jspecify.annotations.Nullable;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;
import java.io.BufferedInputStream;
import java.io.IOException;
Expand Down Expand Up @@ -200,6 +201,13 @@ default Connection newRequest(URL url) {
*/
Connection sslSocketFactory(SSLSocketFactory sslSocketFactory);

/**
* Set a custom hostname verifier to verify the hostname during handshake
* @param hostnameVerifier hostname verifier
* @return this Connection, for chaining
*/
Connection hostnameVerifier(HostnameVerifier hostnameVerifier);

/**
* Add a request data parameter. Request parameters are sent in the request query string for GETs, and in the
* request body for POSTs. A request may have multiple values of the same name.
Expand Down Expand Up @@ -725,6 +733,18 @@ interface Request extends Base<Request> {
*/
void sslSocketFactory(SSLSocketFactory sslSocketFactory);

/**
* Get the current hostname verifier, if any.
* @return hostname verifier if set, null otherwise
*/
@Nullable HostnameVerifier hostnameVerifier();

/**
* Set a custom hostname verifier to verify the hostname during handshake
* @param hostnameVerifier hostname verifier
*/
void hostnameVerifier(HostnameVerifier hostnameVerifier);

/**
* Add a data parameter to the request
* @param keyval data to add.
Expand Down
26 changes: 24 additions & 2 deletions src/main/java/org/jsoup/helper/HttpConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.jsoup.parser.TokenQueue;
import org.jspecify.annotations.Nullable;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.io.BufferedInputStream;
Expand Down Expand Up @@ -222,6 +223,12 @@ public Connection sslSocketFactory(SSLSocketFactory sslSocketFactory) {
return this;
}

@Override
public Connection hostnameVerifier(HostnameVerifier hostnameVerifier) {
req.hostnameVerifier(hostnameVerifier);
return this;
}

@Override
public Connection data(String key, String filename, InputStream inputStream) {
req.data(KeyVal.create(key, filename, inputStream));
Expand Down Expand Up @@ -608,6 +615,7 @@ public static class Request extends HttpConnection.Base<Connection.Request> impl
private CookieManager cookieManager;
private @Nullable RequestAuthenticator authenticator;
private volatile boolean executing = false;
private @Nullable HostnameVerifier hostnameVerifier;

Request() {
super();
Expand Down Expand Up @@ -708,6 +716,14 @@ public void sslSocketFactory(SSLSocketFactory sslSocketFactory) {
this.sslSocketFactory = sslSocketFactory;
}

public HostnameVerifier hostnameVerifier() {
return hostnameVerifier;
}

public void hostnameVerifier(HostnameVerifier hostnameVerifier) {
this.hostnameVerifier = hostnameVerifier;
}

@Override
public Connection.Request ignoreHttpErrors(boolean ignoreHttpErrors) {
this.ignoreHttpErrors = ignoreHttpErrors;
Expand Down Expand Up @@ -1062,8 +1078,14 @@ private static HttpURLConnection createConnection(HttpConnection.Request req) th
conn.setConnectTimeout(req.timeout());
conn.setReadTimeout(req.timeout() / 2); // gets reduced after connection is made and status is read

if (req.sslSocketFactory() != null && conn instanceof HttpsURLConnection)
((HttpsURLConnection) conn).setSSLSocketFactory(req.sslSocketFactory());
if (conn instanceof HttpsURLConnection) {
HttpsURLConnection httpsConnection = (HttpsURLConnection) conn;

if (req.sslSocketFactory() != null)
httpsConnection.setSSLSocketFactory(req.sslSocketFactory());
if (req.hostnameVerifier() != null)
httpsConnection.setHostnameVerifier(req.hostnameVerifier());
}
if (req.authenticator != null)
AuthenticationHandler.handler.enable(req.authenticator, conn); // removed in finally
if (req.method().hasBody())
Expand Down
8 changes: 8 additions & 0 deletions src/test/java/org/jsoup/helper/HttpConnectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.jsoup.integration.ParseTest;
import org.junit.jupiter.api.Test;

import javax.net.ssl.HostnameVerifier;
import java.io.IOException;
import java.net.Authenticator;
import java.net.MalformedURLException;
Expand Down Expand Up @@ -256,6 +257,13 @@ public void caseInsensitiveHeaders(Locale locale) {
assertEquals("foo", con.request().requestBody());
}

@Test public void hostnameVerifier() {
Connection con = HttpConnection.connect("http://example.com/");
HostnameVerifier hostnameVerifier = (hostname, session) -> false;
con.hostnameVerifier(hostnameVerifier);
assertEquals(hostnameVerifier, con.request().hostnameVerifier());
}

@Test public void encodeUrl() throws MalformedURLException {
URL url1 = new URL("https://test.com/foo%20bar/%5BOne%5D?q=white+space#frag");
URL url2 = new UrlBuilder(url1).build();
Expand Down

0 comments on commit 6fa8c9e

Please sign in to comment.