0

I am currently working on implementing a networking model that communicates with a REST API through HTTP in Swift using NSURLSession class.

For preparing the request, I use this code:

    var request = URLRequest(url: requestURL) // url is "http://somethingsomething...
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = body

Now, I am sending the requests that way:

    session.dataTask(with: request) { data, response, error in
       // Parse the data, response and error
    }.resume()

My problem is that I want to check the httpStatusCode of the response in order to inform about possible errors, however, the response inside the completion block is of type URLResponse, not HTTPURLResponse. This means that I have to cast the response to the type HTTPURLResponse. So far I've thought of two ways to approach it - first is to add another error scenario which would handle the "couldn't cast to HTTPURLResponse" scenario, the other way is to simply force the cast to HTTPURLResponse. The first option seems better but it could be just adding some useless code, because maybe the cast will always succeed?

So basically, my question is - can I be sure that, if I send the requests to a HTTP server, the response will always be of HTTPURLResponse type? Or do I have to implement the code that handles a situation where the response object is of a different type or is a nil?

Also, I think it would be good to mention that in my implementation if the completion block returns error that is not nil, the flow will return before trying to cast anything.

user3581248
  • 964
  • 10
  • 22

1 Answers1

0

I believe this is what you need.

session.dataTask(with: request) { data, response, error in
    // Parse the data, response and error
    if let httpResponse = response as? HTTPURLResponse {
        //here it is
        print(httpResponse.statusCode)
    }
}.resume()

I have never had the cast fail to my knowledge. I am not sure why URLResponse and HTTPURLResponse aren't merged into one class, but HTTPURLResponse is a subclass that the response always can be cast to as far as my knowledge goes.

Sethmr
  • 3,046
  • 1
  • 24
  • 42
  • In that case I still have an unhandled scenario where the part `if let httpResponse = response as? HTTPURLResponse` fails. My question is - can I be 100% sure that it won't fail if I am interacting with a HTTP server? – user3581248 Mar 01 '17 at 17:03
  • I use that interacting with an HTTP server on a daily basis and it never fails. – Sethmr Mar 01 '17 at 17:05
  • @user3581248 - No, you can't be guaranteed that it will be `HTTPURLResponse`, which is why you must `if let` or `guard let` to unwrap it safely. Given that the end user doesn't care why it failed, only that it did or not, I check both in my `if`/`guard` statement, e.g. `guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { // handle error here }`. – Rob Mar 01 '17 at 17:13
  • What Rob said, but I believe it is based of the type of response the server sends back. I wouldn't ever just assume that it is, because if you get a failed request or you are using the same block of code to communicate with different servers, then it might fail some of the time. – Sethmr Mar 01 '17 at 17:22
  • I don't think that the variety of servers is important here. It is not a problem to implement handling the failed cast, however, the thought of writing code that would handle an impossible scenario made me ask this question. – user3581248 Mar 01 '17 at 17:26
  • @user3581248 - But it's not an impossible scenario. Just exceedlying unlikely that you have `URLResponse` that's not `HTTPURLResponse`. (This is ignoring, of course, that `response` can, very easily be `nil` if the server is down or there is no internet connection, something that is automatically caught in this `guard let` code.) It's trivial to have one `guard` statement that handles (a) no response; (b) non-`HTTPURLResponse`; and (c) invalid status code; so why wouldn't you? – Rob Mar 01 '17 at 17:42
  • @Rob, if this is some invalid server code, I would like to tell the user exactly which code it is, so that he could bring more info to the app support. If there's no response, or non-`HTTPURLRespoonse`, I think it would also be good to inform that there's something seriously wrong. – user3581248 Mar 01 '17 at 18:19