PRDownloader Custom HTTP Client

In this article, I will show you how to customize a HttpClient for PrDownloader

Create a new class called EvilHostnameVerifier

1
2
3
4
5
6
7
8
9
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSession

class EvilHostnameVerifier: HostnameVerifier {

override fun verify(hostname: String?, sslString: SSLSession?): Boolean {
return hostname == "example.com"
}
}

Copy DefaultHttpClient from PRDownloader library, I name it the EvilHttpClient!

1
2
3
URLConnection
⎿ HttpURLConnection
⎿ HttpsURLConnection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class EvilHttpClient implements HttpClient {

// The original one:
private URLConnection connection;

// Change to this:
private HttpsURLConnection connection;

// Other implementations...

@Override
public void connect(DownloadRequest request) throws IOException {
connection = (HttpsURLConnection) new URL(request.getUrl()).openConnection();
connection.setReadTimeout(request.getReadTimeout());
connection.setConnectTimeout(request.getConnectTimeout());
final String range = String.format(Locale.ENGLISH,
"bytes=%d-", request.getDownloadedBytes());
connection.addRequestProperty(Constants.RANGE, range);
connection.addRequestProperty(Constants.USER_AGENT, request.getUserAgent());
addHeaders(request);

// Add hostname verifier before connect
connection.setHostnameVerifier(new EvilHostnameVerifier());

connection.connect();
}

// Other implementations...

}

Then add the custom HttpClient when initialize PRDownloader.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyApplication : Application() {

// ...

private fun setupPrDownloadManger() {
val config = PRDownloaderConfig.newBuilder()
.setHttpClient(EvilHttpClient())
.setDatabaseEnabled(true)
.setReadTimeout(30000)
.setConnectTimeout(30000)
.build()
PRDownloader.initialize(applicationContext, config)
}
}

There you go, no more “Hostname example.com was not verified”