checking reachability against a specific page in a URL
Asked Answered
F

3

8

After I have read the answer for this question I have found that using reachabilityWithHostName does not work with a URL such as this one: mySite.com/service.asmx , is there anyway to check reachability against this URL using reachabilityWithHostName or any reachability class method ?

thanks so much in advance.

Freehearted answered 8/3, 2012 at 11:25 Comment(1)
Reachability is only there to check if you have internet access so you can determine if you should alert the user and consequently use cached data. This is part of the Apple guidelines for user interaction. If you want to check for a specific URL, then try to access it, setting the timeout to be very small and catch the error.Allethrin
L
17

The Reachability class and -reachabilityWithHostname: is designed to be a quick, fail-fast mechanism to determine whether you have basic network connectivity to the host. If you need to verify that a particular URL can be downloaded, you need to be looking at using NSURLConnection to retrieve the contents of the URL in order to verify that it is truly available.

Depending on whether you need to do this in the foreground or background, you can either use the simple-but-blocking:

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error

or you can use the more complicated method of creating an NSURLConnection object, setting up a delegate to receive responses and wait for those responses to come in.

For the simple case:

 NSURL *myURL = [NSURL URLWithString: @"http://example.com/service.asmx"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myURL];
 [request setHTTPMethod: @"HEAD"];
 NSURLResponse *response;
 NSError *error;
 NSData *myData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];

If you receive back a non-nil myData, you've got some kind of connectivity. response and error will tell you what the server responded to you (in the case of response and if you received a non-nil myData) or what kind of error occurred, in the case of a nil myData.

For the non-trivial case, you can get good guidance from Apple's Using NSURLConnection.

If you don't want to stall your foreground process, you can do this two different ways. The above documentation will provide information on how to implement the delegate, etc. However, a simpler implementation would be to use GCD to send the Synchronous request on a background thread, and then message yourself on the main thread when you are done.

Something like this:

 NSURL *myURL = [NSURL URLWithString: @"http://example.com/service.asmx"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: myURL];
 [request setHTTPMethod: @"HEAD"];
 dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, NULL), ^{
      NSURLResponse *response;
      NSError *error;
      NSData *myData = [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
      BOOL reachable;

      if (myData) {
            // we are probably reachable, check the response
            reachable=YES;
      } else {
            // we are probably not reachable, check the error:
            reachable=NO;
      }

      // now call ourselves back on the main thread
      dispatch_async( dispatch_get_main_queue(), ^{
            [self setReachability: reachable];
      });
 });
Lepto answered 8/3, 2012 at 11:47 Comment(4)
can you provide a simple example of how to do it in the background to prevent hanging of the application ?Freehearted
I've added an example of using GCD to make the synchronous request on an asynchronous call to the background thread, returning the response back to your main thread as a message when it completes. Hope that helps.Lepto
awesome! there is a small mistake in the above code, you have to set reachable = YES in the first if statement and to NO in the second if statement. thank you so much gaige.Freehearted
@brainray thanks for the helpful edit. NOTE: for those wondering why the domain example was changed from MySite.com to example.com, that is a requirement on Stack Overflow.Lepto
R
6

If you want to check reachability against a URL (the one usually used is against a hostname) just do a HEAD request using a NSURLConnection.

Rhapsodize answered 8/3, 2012 at 11:43 Comment(0)
G
4

Swift 5

A possible solution for Swift is:

 func verifyURL(urlPath: String, completion: @escaping (_ isValid: Bool) ->()) {
    if let url = URL(string: urlPath) {
        var request = URLRequest(url: url)
        request.httpMethod = "HEAD"
        let task = URLSession.shared.dataTask(with: request) { _, response, error in
            if let httpResponse = response {
                if httpResponse.getStatusCode() == 200 {
                completion(true)
                }
            } else {
                completion(false)
            }
        }
        task.resume()
    } else {
        completion(false)
    }
}

Then call the method like that:

verifyURL(urlPath: "www.google.com", completion: { (isValid) in
    if isValid {
        runYourCode()
    } else {
        print("URL: www.google.com is not reachable")
    }
})
Graptolite answered 6/8, 2020 at 12:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.