In Java Land, everything is tied up in multiple layers of multi-colored wrapping paper. The abstraction often provides niceties and protections and convenience, etc. But, sometimes it practically makes you forget where you are. For instance, why would anyone write a little howto on requesting something over the web from the context of the web. That should be easy, right? Well, yes, I think so. And it turns out it is in Java, as it is in many other languages. It’s just that there you’re super close to the HTTP protocol all the time, and in many Java uber-frameworks, if you want to know how to break into the low-level operations, you have to know where the fire exit is.
The Right Class
By ‘fire exit’, I mean you have to know what specific API to use. Hehe, and since we’re doing some I/O (a request across the network), be prepared for at least a multi-layered chain of wrapper classes to package the data into.
It turns out that
java.net.HttpUrlConnection are the classes that will give us the operations we need. And the operation is
connection.getInputStream()). So, we have the bits to make a simple helper class for requesting other web resources like REST webservices.
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
It doesn’t consist of too much: Specify your url, open an input stream to that url, read it back, and buffer it into a string response.
But as is often the case, let’s try a little bonus twist…
Internal Https With Invalid Certificate
When I started requesting webservices from my Java app, I needed to connect to an interanl web service that was https only but had a self-signed (not valid) SSL certificate. It turns out that
HttpUrlConnection doesn’t handle https requests. If you request such a resource, you’ll turn up a nice stack trace that includes:
It turns out that Java has another class that’s doing some validation for you. Also in the stack trace,
com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate() is called at
In my case, I didn’t care if the certificate was good because to me it’s an internal, trusted source anyway. So, I want to accept any certificates in my http request.
A TrustManager that Trusts all Certificates
So, when it goes to validate, we need to give it an automatic pass. Here’s the modified
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
So, we pretty much doubled the size of the class, but most of it is on ceremony. There’s no much there. In the static block, we are creating an
SSLContext that has includes a
TrustManager anonymous class in which the method implementations explictly leave out any checking for valid certification of the connection. Plug er in and roll. Or not. Please at least think for a moment if you really know your app, what’s going to use this
UrlReader class and whether it’s a good idea or not, because trusting all “https” connections regardless isn’t a great general philosophy.