2

I am trying to access the custom server response body for 500 errors in class HTTPURLResponse (URLResponse) using URLSession.shared.dataTask function. I can only have access to statusCode and allHeaderFields but it doesn't seem to help.

The equivalent in java for ex. is HttpURLConnection.getErrorStream(), but I cannot find something similar in pure swift (I would like to solve this without using 3rd party libs).

How can I get the text response for the 500 error?

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Andrei F
  • 4,205
  • 9
  • 35
  • 66
  • You can't. 500 is server error, it may send you the response in any form. – Desdenova Oct 19 '18 at 14:50
  • 1
    This varies completely from implementation to implementation. Many web services returns structured or well defined responses with these status codes and you can parse the response out of the first parameter, the `Data` object, passed back to `dataTask` completion handler closure. However, 500 codes generally qualify as unhandled errors and you do not generally expose diagnostic information in the response (in a production environment, at least) for security reasons, and most implementations would not expose any meaningful details here, but rather you'd instead refer internal system logs. – Rob Oct 19 '18 at 14:59

3 Answers3

5
let task = session.dataTask(with: urlRequest) { data, response, error in
    if let data = data, let response = response as? HTTPURLResponse {
        switch response.statusCode {
        case 500...599:
            let yourErrorResponseString = String(data: data, encoding: .utf8)
        default:
            break
        }
    }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
meggar
  • 1,219
  • 1
  • 10
  • 18
  • I used the debugger and it showed that data had 0 bytes so I thought there was a problem with my code. This works, thank you! – Andrei F Oct 19 '18 at 15:23
2

There is no way you can get the response data out of HTTPURLResponse. It only contains header information.

If you want to retrieve the response data, you need to use something like dataTask(with:completionHandler:) to send your request. That function passes (Data?, URLResponse?, Error?) to your completion handler. The data parameter of the completion handler is the data returned by the server.

For example:

import Foundation

let url = URL(string: "http://httpstat.us/500")!

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
    guard let data = data, let response = response as? HTTPURLResponse else {
        return
    }

    switch response.statusCode {
    case 500...599:
        print(String(data: data, encoding: .utf8) ?? "No UTF-8 response data")
    default:
        print("not a 500")
    }
}

task.resume()

Edit: Removed force unwrap according to @Rob‘s suggestion

dlggr
  • 741
  • 7
  • 15
0

There is no way to get more details about a 500 error from the client side.

500 is "Internal Server Error" and it's intentionally vague and unhelpful since disclosing information about the cause of the error would assist hackers in compromising the site.

However you can get a great deal of information about the error from the server log and the log for whatever was processing your code on the server side (php, etc.).

If you have access to the server logs and don't see enough information, you can increase the level of logging for the server and application.

Terry Carmen
  • 3,720
  • 1
  • 16
  • 32