I want to use the URLSession to send a json data that store the detail information to the server bought from vultr. The url is the server ip address and I already set the username and password in the postParams and set the request's httpBody property. The problem is that I can't connect the server.
I thought it should be the problem that I fail to connect to the server. I just buy a server and do nothing to it. The server has a username and a password. I don't know whether I should first setup the server or if I can use it directly after finishing the purchase.
private func sendData() {
let url = URL(string: "https://xxx.xxx.xxx.xxx")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let postParams = "username=root&password=*****"
let postData = postParams.data(using: .utf8)
request.httpBody = postData
let task = URLSession.shared.uploadTask(with: request, fromFile: AppDelegate.data.filename!) { data, response, error in
if let error = error {
print("error: \(error)")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("server error")
return
}
if let mimeType = response.mimeType, mimeType == "application/json", let data = data, let dataString = String(data: data, encoding: .utf8) {
print("got data: \(dataString)")
}
}
task.resume()
}
The error message is shown as followed:
2019-09-07 21:02:46.880119+0800 HeadGaze[2241:445676] Task .<1> finished with error - code: -1004
error: Error Domain=NSURLErrorDomain Code=-1004 "Could not connect to the server." UserInfo={NSUnderlyingError=0x2807e0f30 {Error Domain=kCFErrorDomainCFNetwork Code=-1004 "(null)" UserInfo={_kCFStreamErrorCodeKey=61, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=https://155.138.243.166/, NSErrorFailingURLKey=https://155.138.243.166/, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=61, NSLocalizedDescription=Could not connect to the server.}
Related
I'm using URLSession.dataTask() but I'm getting this error in the console:
Peer disconnected during the middle of a handshake. Sending
errSSLClosedNoNotify
and:
An SSL error has occurred and a secure connection to the server cannot
be made
I open the web in my explorer and it has a valid Goddady SSL certificate recently updated.
And there is a strange detail, when I'm not running the app from xcode, sometimes it works fine.
Here is my code:
let postString = "user=\(user)&pass=\(pass)"
let url = URL(string: "https://www.<<mydomain>>.com/ws/login_ios.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print("Server Error: ", error!)
return
}
}
I'm building an iOS application and I need to access the information on a website. I've located the API endpoint, and was able to get a result in Postman
screenshot of API header and form data
So far I have this code which can allow me to make the request, but how do I parse the response(which is an HTML form, then display response in app
var urlRequest = URLRequest(url: url!)
urlRequest.setValue("application/form-data",forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = "POST"
let postString = "year=2021&season=Outdoor&province=ON&age_group=OPEN&age_sub_group_masters=ALL&age_sub_group_para=ALL&rankings_event=100m&best_by_athlete=1&rankings_event_spec_num=1&is_relay_EVENT=0&page=1"
urlRequest.httpBody = postString.data(using: .utf8)
urlRequest = .init(url: url!)```
I actually found a great resources that showed how to send POST Request with post body, and how to read the response
How To send POST Request
Now it's just a matter of parsing the HTML that is returned, and displaying it in app.
let url = URL(string: Constants.rankingAPI)
guard let requestUrl = url else {
fatalError()
}
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
let postString = "year=2021&season=Outdoor&province=ON&age_group=OPEN&age_sub_group_masters=ALL&age_sub_group_para=ALL&rankings_event=100m&best_by_athlete=1&rankings_event_spec_num=1&is_relay_EVENT=0&page=1"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
// Check for Error
if let error = error {
print("Error took place \(error)")
return
}
// Convert HTTP Response Data to a String
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString.htmlToString)")
}
}
task.resume()
}
Im attemping to make a HTTPRequest using NSURLSession. When I set the full url the request returns the correct data but when using parameters (NSJSONSerialization.dataWithJSONObject -> HTTPBody I get this error
error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
is there something im doing wrong here?
let json = ["api_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(json, options: .PrettyPrinted)
let url = NSURL(string: "https://api.themoviedb.org/3/discover/movie")!
let request = NSMutableURLRequest(URL: url)
request.HTTPBody = jsonData
request.HTTPMethod = "GET"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
if error != nil{
print("Error -> \(error)")
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject]
print("Result -> \(result)")
} catch {
print("Error -> \(error)")
}
}
task.resume()
} catch {
print(error)
}
}
This is not a duplicate! I looked at the suggested answer (none of them worked) before asking this question
In your case that issue can be solved by changing the request.HTTPMethod = "GET" to request.HTTPMethod = "POST"
You should not send HTTP Body in the get request, to send the data with the body you should change HTTPMethod to post
Note: Please check if this api method supports POST requests, if it don't support post you can't use it with http body/post, as per doc i only find 'get' request for the discover/movie which can be like this:
let url = NSURL(string: "http://api.themoviedb.org/3/discover/movie?api_key=YOUR_API_KEY")!
let request = NSMutableURLRequest(URL: url)
request.addValue("application/json", forHTTPHeaderField: "Accept")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { data, response, error in
if let response = response, data = data {
print(response)
print(String(data: data, encoding: NSUTF8StringEncoding))
} else {
print(error)
}
}
task.resume()
Ref: You can check more information from this url: http://docs.themoviedb.apiary.io/#reference/discover/discovermovie/get
I would like with an API -Key and authenticate user . I have the message " Session URL Task Succeeded : HTTP 200 " get in the Console . Unfortunately, I always get the message of the page " {" message " : " . Authorization has been denied for this request " } " . I spent hours looking for and found a solution . I ask for your help . Here is my code :
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let URL = NSURL(string: "https://api.testhomepage.com/api/contact")
let request = NSMutableURLRequest(URL: URL!)
// Headers
request.addValue("ARRAffinity=259dfjiehfs315d7249df8805c7895a98c4cbd3327ffdcb82aaa16317f2e6", forHTTPHeaderField: "Cookie")
request.addValue("Basic dWVzQGp1bGl0ZafdgfvcfgeDcyZS1hZWEyLTQzYmVmMjFhNDMxZQ==", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("api.testhomepage.com", forHTTPHeaderField: "Host")
request.addValue("//api.testhomepage.com/api/contact: POST", forHTTPHeaderField: "https")
request.HTTPMethod = "GET"
// JSON Body
/* Start a new Task */
let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
if (error == nil) {
// Success
let statusCode = (response as! NSHTTPURLResponse).statusCode
print("URL Session Task Succeeded: HTTP \(statusCode)")
let myURLString = "https://api.testhomepage.com/api/contact"
if let myURL = NSURL(string: myURLString) {
var error: NSError?
let myhtml = try! NSString(contentsOfURL: myURL, encoding: NSUTF8StringEncoding)
if let error = error {
print("Error : \(error)")
} else {
print("HTML : \(myhtml)")
}
} else {
print("Error: \(myURLString) doesn't seem to be a valid URL")
}
}
else {
// Failure
print("URL Session Task Failed: %#", error!.localizedDescription);
}
}
task.resume()
}
This is in the console:
URL Session Task Succeeded: HTTP 200
HTML : {"Message":"Authorization has been denied for this request."}
use request.setvalue("", forHTTPHeaderField: "") instead of request.addValue("", forHTTPHeaderField: "")
You cannot populate the Authentication header yourself, period. That header is owned by the URL loading system, and is populated based on credentials in the user's keychain.
You can learn about how to do authentication by reading the authentication chapter of URL Session Programming Guide. Note that the examples are for NSURLConnection, but the rest of the text applies to both.
Alternatively, you can store the credentials in the keychain as an Internet Password item, as described in Keychain Services Programming Guide.
Problem
I would like to use the MailGun service to send emails from a pure Swift app.
Research So Far
As I understand it, there are two methods to send an email via MailGun. One is to email MailGun with the emails, and MailGun will redirect it (See Send via SMTP). That will, as I understand it, not work, as iOS cannot programatically automatically send mail, and must use methods that require user intervention. As such, I should use the API directly. As I understand it, I need to open a URL to do this, and so I should use some form of NSURLSession, as per this SO answer
Code
MailGun provides documentation for Python, which is as follows:
def send_simple_message():
return requests.post(
"https://api.mailgun.net/v3/sandbox(Personal info).mailgun.org/messages",
auth=("api", "key-(Personal info)"),
data={"from": "Excited User <(Personal info)>",
"to": ["bar#example.com", "(Personal info)"],
"subject": "Hello",
"text": "Testing some Mailgun awesomness!"})
with (Personal info) being substituted for keys/information/emails.
Question
How do I do that in Swift?
Thanks!
In python, the auth is being passed in the header.
You have to do a http post request, passing both the header and the body.
This is a working code:
func test() {
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.mailgun.net/v3/sandbox(Personal info).mailgun.org/messages")!)
request.HTTPMethod = "POST"
let data = "from: Excited User <(Personal info)>&to: [bar#example.com,(Personal info)]&subject:Hello&text:Testinggsome Mailgun awesomness!"
request.HTTPBody = data.dataUsingEncoding(NSASCIIStringEncoding)
request.setValue("key-(Personal info)", forHTTPHeaderField: "api")
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
people are getting 400 or 401 errors because none of the other answers construct the url correctly. here is some code that works in swift 5 and iOS15:
func sendEmail() {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = "https://api:YOUR_API_KEY#api.mailgun.net/v3/YOUR_DOMAIN/messages?"
let emailRecipient = "RECIPIENT#EMAIL.COM"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = URLSession.shared
let request = NSMutableURLRequest(url: NSURL(string: mailgunAPIPath + "from=USER#YOUR_DOMAIN&to=\(emailRecipient)&subject=A%20New%20Test%21&text=\(emailMessage)")! as URL)
// POST and report back with any errors and response codes
request.httpMethod = "POST"
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.url!)")
print("response = \(response)")
let httpResponse = response as! HTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
requests.post sends an HTTP POST request, encoding key/value pairs as application/x-www-form-urlencoded. You need to do the same.
convert the set of key-value pairs into application/x-www-form-urlencoded as per How to escape the HTTP params in Swift
compose the request using the resulting string for data & send it as per iOS : http Post using swift
I spent hours trying to get the selected answer working, but to no avail.
Although I was finally able to get this working properly with a large HTTP response. I put the full path into Keys.plist so that I can upload my code to github and broke out some of the arguments into variables so I can have them programmatically set later down the road.
// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = dict["mailgunAPIPath"] as? String
let emailRecipient = "bar#foo.com"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler#<my domain>.com%3E&to=reservations#<my domain>.com&to=\(emailRecipient)&subject=A%20New%20Reservation%21&text=\(emailMessage)")!)
// POST and report back with any errors and response codes
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
The Mailgun Path is in Keys.plist as a string called mailgunAPIPath with the value:
https://API:key-<my key>#api.mailgun.net/v3/<my domain>.com/messages?
Hope this offers a solution to anyone else having issues with MailGun and wanting to avoid a 3rd party solution!
Swift 3 answer:
func test() {
let session = URLSession.shared
var request = URLRequest(url: URL(string: "https://api.mailgun.net/v3/sandbox(Personal info).mailgun.org/messages")!)
request.httpMethod = "POST"
let data = "from: Excited User <(Personal info)>&to: [bar#example.com,(Personal info)]&subject:Hello&text:Testinggsome Mailgun awesomness!"
request.httpBody = data.data(using: .ascii)
request.setValue("key-(Personal info)", forHTTPHeaderField: "api")
let task = session.dataTask(with: request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.url!)")
print("response = \(response)")
let httpResponse = response as! HTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}