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:
You don't need the
var err: NSError!
line (because theerror
object is passed as parameter to the closure). This variable you've declared is not used here.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 oferr
.Likewise, your code is referring to a non-existent class,
NSHHTPURLResponse
. In Swift 3 and later, it'sHTTPURLResponse
.It's probably prudent to do
if let
for the retrieval of theHTTPURLResponse
in order to get thestatusCode
.I'm unclear as to your intent in iterating through
allLinks
, because this connection is just for a givenrequest
, not a bunch of links. Just look at thestatusCode
in light of the particularrequest
. If you need to test multiple URLs, then you do a separaterequest
for each.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
Tableview Image Content Selection Color
Debug View Hierarchy Does Not Render UI
Uisearchcontroller Searchbar Misaligns While Active During Rotation
Conversion Between Cgfloat and Nsnumber Without Unnecessary Promotion to Double
Swift 2.0 Replicate Objc_Association_Retain
Inner Didset Protection Bizarrely Extends to The Whole Class
How to Test Whether an Array's Type Is Optional
Nsurlconnection Throws After Updating to Swift 2.0
Swift Playground with Debugger Support
"'Init' Is Deprecated" Warning After Swift4 Convert
Get Png Representation of Nsimage in Swift
Cmlogitem Timestamp: Why So Complicated
Viewwilllayoutsubviews in Swift
How to Declare Swift Generic for Enums of Particular Type
Cannot Convert [Int] to [Int] in Generic Implementation