NSURL Response Status Meaning

Hi,

I'm fairly new to swift 3 but have done a couple practice apps where I'm going to web pages and pulling data. I started to make a new app but this time when I get the data back it is blank. If I look at the the task response [print(response)] I get the following:


Optional(<NSHTTPURLResponse: 0x61000002e6a0> { URL: https url goes here } { status code: 404, headers {"Strict-Transport-Security" = "max-age=86400";

} })


It seems there is an issue with the security of it being a HTTPS. I have the info.plist settings as:


App Transport Security Settings

Execption Domains

detroit.craigslist.org

NSIncludesSubdomains [Boolean - YES]

NSTemporaryExceptionAllowsInsecureHTTPSLoads [Boolean - YES]

Allow Arbitrary Loads [Boolean - NO]



My question is what can I do to resolve this error so I may pull data from the server? Thanks.




Here is my code:


let group = DispatchGroup()

group.enter()

if let url = URL(string: https url goes here)

let request = NSMutableURLRequest(url: url)

let task = URLSession.shared.dataTask(with: request as URLRequest) {

data, response, error in

if error != nil {

print("error")

} else {

if let unwrappedData = data {

let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)

print(dataString)

}

}

group.leave()

}

task.resume()

}

Thanks and sorry for all the posts. I will try that code tonight. The project summary: I want to have the app go to Craigslist daily with given search parameter (Craigslist puts those parameters in the URL as shown below). Then if a result matches a search term I'm looking for, I want it to save that match and notify me. h ttps://detroit.craigslist.org/search/mcy?hasPic=1&search_distance=100&postal=48152&min_price=1000&max_price=4000&min_auto_year=1990&max_auto_year=2017&auto_title_status=1

Quinn,


Here's the new code with your format:


import UIKit
class ViewController: UIViewController, URLSessionDelegate {

    var session: URLSession!
    @IBAction func refreshData(_ sender: Any) {

        NSLog("start")
        if self.session == nil {
            let config = URLSessionConfiguration.default
            config.requestCachePolicy = .reloadIgnoringLocalCacheData
            self.session = URLSession(configuration: config, delegate: self, delegateQueue: .main)
        }
        let url = URL(string: "h t t p s : / / d e t r o i t . c r a i g s l i s t . o r g")!
        let req = URLRequest(url: url)
        self.session.dataTask(with: req) { (data, response, error) in
            if let error = error as NSError? {
                NSLog("transport error: %@ / %d", error.domain, error.code)
                return
            }
            NSLog("success")
            if let unwrappedData = data {
                let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)
                print("Printing Response...")
                print(response)
                print("Printing Data...")
                print(dataString)

            }
     
            }.resume()


        func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
            NSLog("challenge %@", challenge.protectionSpace.authenticationMethod)
            completionHandler(.performDefaultHandling, nil)
        }

    }
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}



And the output:


2017-08-14 20:46:06.925 Craigslist[1191:26211] start

2017-08-14 20:46:07.429 Craigslist[1191:26211] success

Printing Response...

Optional(<NSHTTPURLResponse: 0x61800003ff00> { URL: h ttps:/

"Strict-Transport-Security" = "max-age=86400";

} })

Printing Data...

Optional(

)

2017-08-14 20:46:07.429 Craigslist[1191:26211] success

So that’s work, right? Which means you should be able to remove your authentication challenge handler entirely, because it’s doing nothing other than logging.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Yes I'm getting the success, but as you can see by the output of (dataString) it's coming up blank despite there being stuff on the page. That's the issue I'm struggling with.

… as you can see by the output of (dataString) it's coming up blank despite there being stuff on the page. That's the issue I'm struggling with.

Ah, that’s a completely different kettle of fish. I’ll respond below (because this indentation is getting out of control)-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

… as you can see by the output of (dataString) it's coming up blank despite there being stuff on the page. That's the issue I'm struggling with.

With reference to the code you posted on 15 Aug, there’s a bunch of potential issues:

  • First, you should be using Swift’s

    String
    here, not Foundation’s
    NSString
    . This isn’t the cause of your problem, but programming in Swift is easier if you stick with Swift’s standard data types.
  • Next, you shouldn’t look at the data passed to your completion handler without first looking at the response’s status code. The fact that

    error
    is nil only tells you that
    URLSession
    was able to send the request to a server and get a response back. It doesn’t tell you that the request was successful on the server. You should always check the response status code (like the
    statusCode
    property) to verify that the response is valid.
  • It’s also a good idea to check the response content type (via the

    mimeType
    property). In some cases (including captive networks and HTTP proxies) you can get a response that didn’t come from the origin server. In that case the body of the response may not be of the type you expect, and thus you should check for the type.

Putting all of the above together a typical completion handler should look like this:

let task = self.session.dataTask(with: request) { (data, response, error) in
    if let error = error {
        // … report transport error …
        return
    }
    let response = response as! HTTPURLResponse
    let data = data!
    guard response.statusCode == 200 else {
        // … report server error …
        return
    }
    guard response.mimeType == "text/plain" else {
        // … report server error …
        return
    }
    NSLog("%@", data as NSData)
}

Once you know the type of the data you can reasonably parse it. How you do that depends on the type itself. My guess is that you’re dealing with

text/html
data. Is that right?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Ok that makes sense. So I was there was a connection, but seeing a blank rather than any error because I wasn't checking the response. I get no output, but when I check, it's getting hung up in the guard response.statusCode == 200 block.

So what’s

statusCode
?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

<NSHTTPURLResponse: 0x610000032800> { URL: https:/

"Strict-Transport-Security" = "max-age=86400";

} }

That’s a print out of the response object which, alas, does not show the status code. I’m looking for the

statusCode
property of that response, which you can fetch using the code from line 8 of the snippet in my 16 Aug post.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I see where that line of code is (the 'return' part right?), however it's coming up blank for me. I put print statements in to verify it's going through that block of code, but the return part comes back blank.


guard response.statusCode == 200 else {
    print("Server Error")
    return
}



Output:

Server Error

If you want the code, you should ask to print it :


guard response.statusCode == 200 else {
    print("Server Error ", response.statusCode)
    return
}

I get this as the output:

Server Error 404

You know 404 : means the resource (typically the page) was not found on the server.


Check the url in your request ; try to access it manually in Safari to see if you get the same error.

No the URL (craigslist) works fine in my browser. I think there's something about the security of the site that it's running into problems with.


"Strict-Transport-Security" = "max-age=86400";

NSURL Response Status Meaning
 
 
Q