I am unable to make a successful POST request in swift. It shows an the following
error"kCFStreamErrorCodeKey=-9847,NSErrorFailingURLStringKey=https://192.168.1.167:8100/Attendance/login,".
It worked perfectly with my older version of swift. Now I have updated my Xcode and this issue occurred.
func logSetRequest(){
let urlString = "https://192.168.1.167:8100/Attendance/login"
let url = NSURL(string: urlString)
let theRequest = NSMutableURLRequest(URL: url!)
theRequest.HTTPMethod = "POST"
let parameters = [ "email": usernameTxtField.text!,"password": passwordTxtField.text!] as Dictionary<String, String>
var err: NSError?
do {
theRequest.HTTPBody = try NSJSONSerialization.dataWithJSONObject(parameters, options: [])
} catch let error as NSError {
err = error
theRequest.HTTPBody = nil
} // pass dictionary to nsdata object and set it as request body
theRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
theRequest.addValue("application/json", forHTTPHeaderField: "Accept")
var connectRequest = NSURLConnection(request: theRequest, delegate: self)
logActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
I have made relevant changes in plist also
From googling it seems that error code -9847 has something to do with SSLHandshake failing.
You said that you've upgraded to a new version of Swift. In iOS 9.0/OS X 10.11 Apple introduced App Transport Security, which requires you to run HTTPS, which you also do. But maybe there is something wrong with the HTTPS setup that worked before, but has stopped working under iOS 9.
You can read more about ATS (and how to temporarily disable it) here:
http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/
Hope that helps
Related
Problem
I recently updated my iPhone to iOS 10.3.1 and Xcode to Version 8.3.2. Currently, I have an app which runs a few URLRequests once my app launches.
However, after updating both iOS and Xcode, the app occasionally return an error message:
error in connection_block_invoke_2: Connection interrupted
The message is quite vague but I assumed it has something to do with the URLRequests since it mentions "Connection interrupted".
Whenever this error message appears, it will "freeze" the app for ~5s before getting the data from the server.
Question
So, what does this error message actually mean? And how can I minimise it or fix it?
Example of one URLRequest:
func checkLogin () {
let username = txtUsername.text!
let password = txtPassword.text!
let post = "username=\(username)&password=\(password)"
NSLog("PostData: %#",post);
let url:URL = URL(string:"https://example.com/login.php")!
let postData = post.data(using: .utf8)!
let postLength = String( postData.count )
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = postData
request.setValue(postLength as String, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
return
}
if let jsonData = (try? JSONSerialization.jsonObject(with: data!, options: [])) as? [String:Any] {
let success = jsonData["success"] as! Int
if success == 1 {
//do something,
}
else {
//show alert
}
}
})
task.resume()
}
Duplicates
The following questions does not solve my problem as:
What is "error in __connection_block_invoke_2: Connection interrupted" in iOS?
I didn't receive any memory warning so the answer does not apply.
iOS: error in __connection_block_invoke_2: Connection interrupted
I didn't use AVCaptureMovieFileOutput and AVCaptureVideoDataOutput at all in my app, thus the answer also doesn't apply.
error in __connection_block_invoke_2: Connection interrupted on iPad & Xcode 7 error message "error in __connection_block_invoke_2: Connection interrupted" when app runs on iPad
No answer at all.
I can't get the URLSession to send anything in the body of a POST request.
Here is my code:
// Set up the request
var request = URLRequest(url: URL(string: baseURL + url)!)
request.httpMethod = "POST"
let jsonData = try JSONSerialization.data(withJSONObject: values,
options: .prettyPrinted)
request.httpBody = jsonData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let config = URLSessionConfiguration.ephemeral
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
let task = session.dataTask(with: request) { data, response, err in
if let err = err {
print(err)
}
else {
let jsondata = data!
do {
let sessionData =
try JSONSerialization.jsonObject(with: jsondata, options: .mutableLeaves)
as? Dictionary<String, String>
callback.taskComplete(response: sessionData, task: task)
}
catch {
print(error)
}
}
}
task.resume()
The server receives the request, but the body is empty and the content type header is null. I can't use the default session because I'm developing with self-signed certificates, so I need my class to be a URLSession delegate.
I'm using Swift 3, XCode 8, and iOS 10. Any help would be appreciated.
Problem solved. It was a combination of errors. If the URL doesn't have the trailing "/", Jetty sends a 302 redirect to the same URL with the slash appended. The iOS client does the redirect with a "GET," so there is nothing in the body. When I add the trailing "/", the request works fine.
I hope this answer will help someone doing iOS development. I searched Google for hours before I posted this question. I finally found the answer in a post about the Apache Java HttpClient. It has the same behavior.
Thank you for all the responses.
I cannot for the life of me figure out this problem. And I hope you guys can.
I want to send a username and a password over a HTTPS POST. Problem is, I cannot make it work.
The code I am trying to make work right now is:
import UIKit
import Foundation
import PlaygroundSupport
let url:URL = URL(string: "https://mywebsite.com/myAPI")!
let session = URLSession.shared
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let paramString = "username=Pleasework&password=itwont"
request.httpBody = paramString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest) {
(
data, response, error) in
guard let data = data, let _:URLResponse = response, error == nil else {
print("error")
return
}
let dataString = String(data: data, encoding: String.Encoding.utf8)
print(dataString ?? "Got nothing")
}
task.resume()
Looking at my server logs, this request goes through, but it is supposed to create a file containing said params. I tried using a Chrome extension called "Request Maker", and the file was created. (The file is created with PHP, and is irrelevant to this question)I found that the file was only created once the content type was specified, so I tried that in Swift.
I am using Swift 3 and Xcode 8, I hope you guys can help me send a simple post request with a content type to a URL, all of the other answers on Stackoverflow have not helped me.
Thanks
I am using Fabric SDK to add the twitter login button in my app.......
i add the authentication header in my URL but still it is showing Bad authentication error while executing.
Suggest me how to add Header in the URL in Swift.
let twitter = Twitter.sharedInstance()
let oauthSigning = TWTROAuthSigning(authConfig:twitter.authConfig, authSession:twitter.session())
let authHeaders = oauthSigning.OAuthEchoHeadersToVerifyCredentials()
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.twitter.com/1.1/search/tweets.json?q=Himan_dhawan")!)
request.allHTTPHeaderFields = authHeaders
println(request)
var session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if((error) != nil) {
println(error.localizedDescription)
}
var strData = NSString(data: data, encoding: NSASCIIStringEncoding)
println(strData)
})
task.resume()
It's to do with the way that you're setting the headers on the request.
The Fabric doc's don't quite give you the full picture about creating the OAuth signing headers when wanting to use your own NSMutableURLRequest.
let authHeaders = oauthSigning.OAuthEchoHeadersToVerifyCredentials()
The return [NSObject : AnyObject]! dictionary gives you the values you need for the request. However, what it provides for the headers are different to what needs to be sent with the NSMutableURLRequest.
This is how you should be setting the headers for this request:
let twitter = Twitter.sharedInstance()
let oauthSigning = TWTROAuthSigning(authConfig:twitter.authConfig, authSession:twitter.session())
let authHeaders = oauthSigning.OAuthEchoHeadersToVerifyCredentials()
let mutableUrlWithUsableUrlAddress = NSMutableURLRequest(URL: usableUrlForRequest)
mutableUrlWithUsableUrlAddress.addValue(authHeaders[TWTROAuthEchoAuthorizationHeaderKey] as? String, forHTTPHeaderField: "Authorization")
This sets the required Authorisation Key as a value for the "Authorization" header on the request, opposed to when you pass in the authHeaders dictionary, it gets set for "X-Verify-Credentials-Authorization".
The Fabric doc's do go into this, but it's slightly more tucked away than it should be.
Can anybody help on connecting issue swift ios with soap object
var soapMessage = "<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'><soap:Body> <BindCategory xmlns=‘http://tempuri.org/'></BindCategory></soap:Body></soap:Envelope>"
var urlString = "http://assetwebservice.sudesi.in/service.svc"
var msgLength = String(count(soapMessage))
var url = NSURL(string: urlString)!
var theRequest = NSMutableURLRequest(URL: url)
theRequest.addValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type")
theRequest.addValue("http://tempuri.org/IService/BindCategory", forHTTPHeaderField: "Soapaction")
theRequest.addValue(msgLength, forHTTPHeaderField: "Content-Length")
theRequest.HTTPMethod = "POST"
theRequest.HTTPBody = soapMessage.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
var connection = NSURLConnection(request: theRequest, delegate: self,startImmediately: true)
connection?.start()
if (connection == true) {
println("Connection success")
var mutableData : Void = NSMutableData.initialize()
}else{
println("Error in connection")
}
Well, the thing that jumps out at me is the following:
if (connection == true) {
println("Connection success")
// What does this line mean? I can't make sense of it.
var mutableData : Void = NSMutableData.initialize()
}
You are comparing an NSURLConnection? to a Bool. This is never going to be true. Besides, this is not the correct way to determine whether a connection is successful. NSURLConnection has an optional initializer so that it can check whether its parameters are valid, not so that the success of a connection can be determined. Success will be determined by the appropriate callbacks to the delegate.
You should look into using NSURLSession instead of NSURLConnection unless you have to support iOS < 7.0, which I doubt. I have a suspicion—perhaps false—that the questioner is a C# programmer doing Swift who is perhaps not familiar with the delegate pattern, which is common in Apple's frameworks but not common at all in Microsoft's. If so, NSURLSession's interface will be much more palatable.
Issue is in soap envevlope mapping , now I have correct that , all things are now perfect.
Thanks