Preferred Java Way to Ping an Http Url for Availability

Preferred Java way to ping an HTTP URL for availability

Is this any good at all (will it do what I want?)

You can do so. Another feasible way is using java.net.Socket.

public static boolean pingHost(String host, int port, int timeout) {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(host, port), timeout);
return true;
} catch (IOException e) {
return false; // Either timeout or unreachable or failed DNS lookup.
}
}

There's also the InetAddress#isReachable():

boolean reachable = InetAddress.getByName(hostname).isReachable();

This however doesn't explicitly test port 80. You risk to get false negatives due to a Firewall blocking other ports.


Do I have to somehow close the connection?

No, you don't explicitly need. It's handled and pooled under the hoods.


I suppose this is a GET request. Is there a way to send HEAD instead?

You can cast the obtained URLConnection to HttpURLConnection and then use setRequestMethod() to set the request method. However, you need to take into account that some poor webapps or homegrown servers may return HTTP 405 error for a HEAD (i.e. not available, not implemented, not allowed) while a GET works perfectly fine. Using GET is more reliable in case you intend to verify links/resources not domains/hosts.


Testing the server for availability is not enough in my case, I need to test the URL (the webapp may not be deployed)

Indeed, connecting a host only informs if the host is available, not if the content is available. It can as good happen that a webserver has started without problems, but the webapp failed to deploy during server's start. This will however usually not cause the entire server to go down. You can determine that by checking if the HTTP response code is 200.

HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
// Not OK.
}

// < 100 is undetermined.
// 1nn is informal (shouldn't happen on a GET/HEAD)
// 2nn is success
// 3nn is redirect
// 4nn is client error
// 5nn is server error

For more detail about response status codes see RFC 2616 section 10. Calling connect() is by the way not needed if you're determining the response data. It will implicitly connect.

For future reference, here's a complete example in flavor of an utility method, also taking account with timeouts:

/**
* Pings a HTTP URL. This effectively sends a HEAD request and returns <code>true</code> if the response code is in
* the 200-399 range.
* @param url The HTTP URL to be pinged.
* @param timeout The timeout in millis for both the connection timeout and the response read timeout. Note that
* the total timeout is effectively two times the given timeout.
* @return <code>true</code> if the given HTTP URL has returned response code 200-399 on a HEAD request within the
* given timeout, otherwise <code>false</code>.
*/
public static boolean pingURL(String url, int timeout) {
url = url.replaceFirst("^https", "http"); // Otherwise an exception may be thrown on invalid SSL certificates.

try {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setConnectTimeout(timeout);
connection.setReadTimeout(timeout);
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
return (200 <= responseCode && responseCode <= 399);
} catch (IOException exception) {
return false;
}
}

How to ping an IP address

You can not simply ping in Java as it relies on ICMP, which is sadly not supported in Java

http://mindprod.com/jgloss/ping.html

Use sockets instead

Hope it helps

How to validate a URLs status

You can use java.net.HttpURLConnection for this as in the sample below. The key here is the getResponseCode method that will return the HTTP code, i.e. 200, 400... .

package so;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class HttpRequest {

private int getWebPageStatus(String url) {

HttpURLConnection con = null;
try {
con = (HttpURLConnection) new URL(url).openConnection();
return con.getResponseCode();

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (con != null) {
con.disconnect();
}
}

return -1;
}

public static void main(String[] args) {
HttpRequest request = new HttpRequest();

System.out.println("https://login.yahoo.com :" + request.getWebPageStatus("https://login.yahoo.com"));
System.out.println("https://www.google.co.in :" + request.getWebPageStatus("https://www.google.co.in"));
System.out.println("https://www.gmail.com :" + request.getWebPageStatus("https://www.gmail.com"));
System.out.println("https://xyz.co.in :" + request.getWebPageStatus("https://xyz.co.in"));
}

}

Alternative suggestions for this Ping function?

You could also use the Socket class provided in the java.net package.
Using the provided method connect(SocketAddress endpoint) you can connect your socket to the server.

For example, you can use something like this

 public static boolean ping(String address, int port) {
Socket socket = new Socket();
try {
socket.connect(new InetSocketAddress(address, port));
} catch (IOException e) {
return false;
} finally {
try {
socket.close();
} catch (IOException ignored) { }
}
return true;
}

You can invoke like this ping("www.google.com", 443)

Finally, you could use the java.net.URL class to wrap your String url.
For instance,

URL url = new URL("https://www.google.com:443/");
ping(url.getHost(), url.getPort());


Related Topics



Leave a reply



Submit