How to Test a Url and Get a Status Code in Swift 3

How do you test a URL and get a status code in Swift 3?

try this out to give you the status codes of the responses - 200, 404 etc:

let url = URL(string: fullURL)

let task = URLSession.shared.dataTask(with: url!) { _, response, _ in
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
}
}

task.resume()

You could also do the same, simply replacing the with: url! to use the request var as you defined in your example e.g. let task = URLSession.shared.dataTask(with: request) {...} But in this example I don't think you need to really.

How To Check Response.statusCode in sendSynchronousRequest on Swift

you pass in a reference to response so it is filled THEN you check the result and cast it to a HTTPResponse as only http responses declare the status code property.

let urlPath: String = "http://www.google.de"
var url: NSURL = NSURL(string: urlPath)
var request: NSURLRequest = NSURLRequest(URL: url)
var response: NSURLResponse?

var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData?

if let httpResponse = response as? NSHTTPURLResponse {
println("error \(httpResponse.statusCode)")
}

note: in objC you would also use the same approach but if you use squared brackets, the compiler doesn't enforce the cast. Swift (being type safe) does enforce the cast always

Get HTTP Status using swift

The fundamental issue here is that you appear to be looking at the statusCode only if the err is not nil. But if you have error, you probably don't have status code. The error parameter to the closure indicates fundamental network issue that probably prevented you from getting to the page in question. The statusCode is generally only meaningful if the error was nil (i.e. you succeeded in connecting to the server), in which case the statusCode is how the server informs you of its ability to service the HTTP request.

A couple of minor things:

  1. You don't need the var err: NSError! line (because the error object is passed as parameter to the closure). This variable you've declared is not used here.

  2. I don't see how error: err as the third parameter to the closure could have worked. The syntax is "variableName: variableType", but there is no type of err.

  3. Likewise, your code is referring to a non-existent class, NSHHTPURLResponse. In Swift 3 and later, it's HTTPURLResponse.

  4. It's probably prudent to do if let for the retrieval of the HTTPURLResponse in order to get the statusCode.

  5. I'm unclear as to your intent in iterating through allLinks, because this connection is just for a given request, not a bunch of links. Just look at the statusCode in light of the particular request. If you need to test multiple URLs, then you do a separate request for each.

  6. We should consider any codes between 200 and 299 as success, not just 200. I'd suggest using the range 200 ..< 300.

Thus:

let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, let httpResponse = response as? HTTPURLResponse, error == nil else {
print("No valid response")
return
}

guard 200 ..< 300 ~= httpResponse.statusCode else {
print("Status code was \(httpResponse.statusCode), but expected 2xx")
return
}

// everything OK, process `data` here
}
task.resume()

I also made a few other changes (updated for Swift 3 and later; use URLSession rather than URLConnection; I think error is fine choice for the variable name; I prefer the trailing closure syntax; I tend to use inferred types for closure parameters to make the declaration a little more concise, etc.), but all of that is immaterial to the question at hand: Hopefully this illustrates how one checks the status code.

For Swift 2 rendition, see previous revision of this answer.

handling HTTP status code with URLSession and Combine

If I correctly understood your goal, you need something like

}else{
return Fail(error: ServiceError.badServiceReply)
.eraseToAnyPublisher()
}

Simple example:

URLSession.shared
.dataTaskPublisher(for: URL(string: "https://www.google.com")!)
.receive(on: DispatchQueue.main)
.flatMap { _ in
Fail(error: URLError(URLError.unsupportedURL)).eraseToAnyPublisher()
} //for the sake of the demo
.replaceError(with: "An error occurred") //this sets Failure to Never
.assign(to: \.stringValue, on: self)
.store(in: &cancellableBag)

would always assign string "An error occurred" due to remap to Fail publisher

Checking Http Status Swift4

Try this code

func checkStatusCode(response:URLResponse?) -> Bool {
guard let statusCode = (response as? HTTPURLResponse)?.statusCode else {
print("Invalid Response")
return false
}

if statusCode != 200 {
print("Invalid File")
return false
}
return true
}

Usage:

if (self.checkStatusCode(response: response)) { 
DispatchQueue.main.async {
self.performSegue(withIdentifier: "showW", sender: self)
}
} else {
//added an alert
}

How to check the status code is whether 200 or not?

let statusCode: Int? = {
if let httpUrlResponse = response as? HTTPURLResponse {
return httpUrlResponse.statusCode
}
return nil
}()

And then compare it to 200

How to make HTTP request in Swift?

You can use URL, URLRequest and URLSession or NSURLConnection as you'd normally do in Objective-C. Note that for iOS 7.0 and later, URLSession is preferred.

Using URLSession

Initialize a URL object and a URLSessionDataTask from URLSession. Then run the task with resume().

let url = URL(string: "http://www.stackoverflow.com")!

let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}

task.resume()

Using NSURLConnection

First, initialize a URL and a URLRequest:

let url = URL(string: "http://www.stackoverflow.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST"

Then, you can load the request asynchronously with:

NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue.main) {(response, data, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}

Or you can initialize an NSURLConnection:

let connection = NSURLConnection(request: request, delegate:nil, startImmediately: true)

Just make sure to set your delegate to something other than nil and use the delegate methods to work with the response and data received.

For more detail, check the documentation for the NSURLConnectionDataDelegate protocol

Testing on an Xcode playground

If you want to try this code on a Xcode playground, add import PlaygroundSupport to your playground, as well as the following call:

PlaygroundPage.current.needsIndefiniteExecution = true

This will allow you to use asynchronous code in playgrounds.



Related Topics



Leave a reply



Submit