I have an interesting problem: when my device is in Airplane Mode, the HTTP Status Code that the NSHHTPURLResponse provides is 200 "OK".
Shouldn't it fail with an error, or at least not respond that it has a valid connection with code 200?
Here is a snipit of my code:
let url = NSURL(string: "http://apple.com");
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
if(error == nil){
let statusCode = (response as! NSHTTPURLResponse).statusCode;
if(statusCode == 200){
println("All Good");
}
}
}
task.resume();
In Airplane Mode, "All Good" is printed
Don't test error, test the data returned. Error (NSError, ErrorType) is used to return errors from the callback (inout).
The code below works for me.
I edited it with idiomatic Swift syntax:
let urlPath = "https://www.google.com/"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!) { data, response, error in
if data != nil {
NSLog("%#", NSString(data: data!, encoding: NSUTF8StringEncoding)!) // EDIT
let res = response as? NSHTTPURLResponse
if res?.statusCode == 200 {
NSLog("All Good")
}
}
}
task!.resume()
Seems you may be getting an cached response. Check this article out.
.reloadIgnoringLocalCacheData
should solve your issue if this is the cause.
cachepolicy
Related
I'm trying to make GET request. Url is configured without slash at the end of URL. Server receives url with "/" at the end so I get error 404. I can see response.url with slash, but urlRequest contains URL without it.
Can't understand, what's going on.
Meant to send:
http://someUrl.com/api
Sent:
http://someUrl.com/api/
Code sample
guard let url = URL(string: self.rootUrl + "/api") else {
print ("Can't make URL")
return
}
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "GET"
let sessionConf = URLSessionConfiguration.default
let session = URLSession.init(configuration: sessionConf)
let task = session.dataTask(with: urlRequest) {
(data, response, error) in
// check for any errors
guard error == nil else {
print("error calling GET on /api")
print(error!)
return
}
// make sure we got data
guard let responseData = data else {
print("Error: did not receive data")
return
}
// parse the result as JSON, since that's what the API provides
do {
print (urlRequest)
let json = try? JSONSerialization.jsonObject(with: responseData) as? [String: Any]
if ( json == nil ) {
print ("error json")
print(response!)
} else { ....
Swift cached response for this request, set CachePolicy to ignore reload and try to do GET request to other URL and than try again.
So when I send request without any cookies I get an error.
when trying to get request manually (in a browser) I first need to go to homepage, which loads 4 cookies, then the request can proceed without error. Some experimenting showed that I need only one of the cookies.
This is completely new to me and any snippets/guides on how this can be implemented are welcome. I understand that this question Is pretty vague but I am lost in where to start looking and would appreciate any help
let url = URL(string: "homepage")
var request = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil, let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
print("response1")
print("error = \(error)")
print("response = \(response)")
return
}
if let json = try? JSONSerialization.jsonObject(with: data) {
print("responseObject = \(json)")
} else {
print("response2")
print("responseString = \(String(data: data, encoding: .utf8))")
}
let url2 = URL(string: "requestpage")
var request = URLRequest(url: url2!)
request.setValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil, let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
print("response2")
print("error = \(error)")
print("response = \(response)")
return
}
if let json = try? JSONSerialization.jsonObject(with: data) {
print("responseObject = \(json)")
} else {
print("response2")
print("responseString = \(String(data: data, encoding: .utf8))")
}
}
task.resume()
}
task.resume()
In your code, you should:
initiate URLSessionTask for the landing page that sets the cookies;
that will, with no intervention on your part, will set the cookies in your URLSession;
after that response is successfully received, you can then send the next request and the cookies should be there automatically with no extra code.
Unless you did something to explicitly interfere with this process, URLSession seamlessly receives the the cookies and includes them in subsequent requests for you.
If you're scraping a web site (and if so, please check the ToS to make sure it's permitted), you are well advised to request the pages in the same order that a web browser would. It might feel like you could bypass that landing page and set the cookies yourself, but often the cookie values are generated dynamically and you can have problems if you try to bypass that landing page.
You asked for an example, and there's really not much to show. Just initiate second request from the completion of the first request. There's not a single reference to cookies in the Swift code. URLSession takes care of everything:
let url = baseURL.appendingPathComponent("setcookie.php")
var request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil, let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
print("error = \(error)")
print("response = \(response)")
return
}
let url = baseURL.appendingPathComponent("results.php")
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil, let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
print("error = \(error)")
print("response = \(response)")
return
}
if let json = try? JSONSerialization.jsonObject(with: data) {
print("responseObject = \(json)")
} else {
print("responseString = \(String(data: data, encoding: .utf8))")
}
}
task.resume()
}
task.resume()
My first page, setcookie, just set a cookie:
<?php
setcookie("foo", "bar", time()+3600);
$result = array("success" => true);
echo json_encode($result);
?>
And my second page retrieved the cookies:
<?php
$result = array("success" => true);
if (isset($_COOKIE))
$result["_COOKIE"] = $_COOKIE;
header("Content-Type: application/json");
echo json_encode($result);
?>
And the above Swift code output:
responseObject = {
"_COOKIE" = {
foo = bar;
};
success = 1;
}
Im trying to get html data from shoutoutStream , actually currently playing title...
I'm new at swift programming so i really need a help.
This is what i've tryied but still getting error:
ICY 404 Resource Not Found
icy-notice1:SHOUTcast Distributed Network Audio Server/Linux v1.9.8
icy-notice2:The resource requested was not found
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: NSURL(string: "http://s5.voscast.com:8220/7.html")!)
let task = session.dataTaskWithRequest(request, completionHandler: {
(data, response, error) -> Void in
var usedEncoding = NSASCIIStringEncoding
print(usedEncoding)// Some fallback value
if let encodingName = response?.textEncodingName {
let encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName))
if encoding != UInt(kCFStringEncodingInvalidId) {
usedEncoding = encoding
}
}
if let myString = String(data: data!, encoding: usedEncoding) {
print("this is my string: \(myString)")
} else {
print("failed to decode data")
}
})
task.resume()
Please help me , i'm sooo frustrated already.
I'm following an iOS Swift guide on Udemy and this is the first issue I cannot work around:
I am supposed to see html etc printed to the console but instead I get null.
This is the section:
let url = NSURL(string: "https://google.com")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {
(data, response, error) in
if error == nil {
var urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding)
print(urlContent)
}
}
task.resume()
If I print just the data then it gives me some content back but when its encoded its nil.
Any help? Cannot move onto the next part until this is resolved.
The problem there as already mentioned by rmaddy it is the encoding you are using. You need to use NSASCIIStringEncoding.
if let url = URL(string: "https://www.google.com") {
URLSession.shared.dataTask(with: url) {
data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let data = data, error == nil,
let urlContent = String(data: data, encoding: .ascii)
else { return }
print(urlContent)
}.resume()
}
Or taking a clue from Martin R you can detect the string encoding from the response:
extension String {
var textEncodingToStringEncoding: Encoding {
return Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(self as CFString)))
}
}
if let url = URL(string: "https://www.google.com") {
URLSession.shared.dataTask(with: url) {
data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let data = data, error == nil,
let textEncoding = response?.textEncodingName,
let urlContent = String(data: data, encoding: textEncoding.textEncodingToStringEncoding)
else { return }
print(urlContent)
}.resume()
}
I have an application that retrieves JSON data from my server and enters it in to my Core Data model. I have this working reasonably well, minus a few issues with random EXC_BAD_ACCESS errors that I haven't figured out yet. During this dataTask, it can retrieve large amounts of data so it can take a while to complete.
I'm looking for a way to let the user suspend the app the dataTask will continue to retrieve the data. I seen NSURLSession has a background mode, but seen it only supports upload and download tasks.
Is there a way to support this?
My dataTask function:
class func Request(file: String, withData: String?, completion: (NSData -> Void)) {
let url = NSURL(string: "\(root)\(file)")!
let request = NSMutableURLRequest(URL: url)
if let sentData = withData {
request.HTTPMethod = "POST"
request.HTTPBody = sentData.dataUsingEncoding(NSUTF8StringEncoding)
}
let dataTask = session.dataTaskWithRequest(request) {
data, response, error in
if error != nil {
if error?.domain == NSURLErrorDomain && error?.code == NSURLErrorTimedOut {
print("Data task timed out")
}
} else {
let httpResponse : NSHTTPURLResponse = response as! NSHTTPURLResponse
if httpResponse.statusCode == 200 {
completion(data!)
} else {
print("Request failed with status code: \(httpResponse.statusCode)")
}
}
}
dataTask.resume()
}