How to POST request in Swift - ios

I have this API http://my-api.mydoctorfinder.com/
that will return a bool value depending on the email and password you have entered.
My problem is it will always return false despite using the correct email and password.
I was thinking that I might have not sent the right parameter since I created a dictionary containing the email and password. Then passed it on NSJSONSerialization.dataWithJSONObject method
By the way, I was using SwiftyJson.
This is my code
//creates a dictionary and calls the PostRequest method
func attemptLogIn( email: String, password: String) {
let route = loggerURL
let body: [String:String] = ["email":email, "password":password]
makeHTTPPostRequest(route, body: body)
}
//performs post request
private func makeHTTPPostRequest(path: String, body: [String: AnyObject]) {
let request = NSMutableURLRequest(URL: NSURL(string: path)!)
// Set the method to POST
request.HTTPMethod = "POST"
do {
// Set the POST body for the request
let jsonBody = try NSJSONSerialization.dataWithJSONObject(body, options: .PrettyPrinted)
request.HTTPBody = jsonBody
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let jsonData = data {
let json:JSON = JSON(data: jsonData)
//onCompletion(json, nil)
print("The Response: ")
print(json)
} else {
//onCompletion(nil, error)
print("The Response: ")
print("Hello")
}
})
task.resume()
} catch {
// Create your personal error
//onCompletion(nil, nil)
}
}

The response is simply a true or false i.e. its not a json object.
So i would suggest don't use Swifty son instead use Alamofire.
Following code should work for you:-
let myParameters = [
"email": "your email id",
"password": "your password"]
Alamofire.request(.POST, "http://my-api.mydoctorfinder.com/ ", parameters: myParameters)
.response { request, response, data, error in
print(request)
print(response)
if(response == true)
{
// do your thing
}
print(error)
}
Note: There might be a need to typecast response to bool
Also following is the screenshot of the link you gave, it returns true(and not a json object) [After registration, i tried to login with same credentials]

Try to create JSON object using NSJSONSerialization in this way:
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(body, options: [])
I assume that problem is in .PrettyPrinted constant.
Edit:
Also try adding correct content-type:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")

Here is the swift post request to get data :
func retriveTextDataByPost(requestURL:String, params: NSDictionary, handler:((dict:NSDictionary?) -> Void)) {
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let url = NSURL(string: requestURL)
let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.UseProtocolCachePolicy, timeoutInterval: 60)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPMethod = "POST"
do {
let postData = try NSJSONSerialization.dataWithJSONObject(params, options:NSJSONWritingOptions.PrettyPrinted)
request.HTTPBody = postData
let postDataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
if data != nil {
do {
let dictResult:NSDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
handler(dict: dictResult)
} catch { }
}
}
postDataTask.resume()
} catch { }
}

Check your keys for email and password with required input for APIs
Check your login URL

Related

Swift HTTP Post Request returns HTML of site instead of JSON response

I am trying to reach a site that should take the username and password given and return a JSON which contains information stating whether or not the login data provided was valid or not.
However, all I'm getting back is the site's HTML code instead of a response. I've tried the request with the same parameters on https://www.hurl.it/ and have gotten the correct response so that does not seem to be the issue.
I use the following code:
private func uploadToAPI(username: String, password: String) {
guard let url = URL(string: "http://api.foo.com/login.php"),
let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics),
let encodedPassword = password.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics) else {
self.loginButton.isLoading = false
return
}
let httpBodyParameters = ["user": encodedUsername, "password": encodedPassword, "client": "ios", "version": "5"]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: httpBodyParameters, options: JSONSerialization.WritingOptions.prettyPrinted)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response.mimeType) // Prints "text/html"
}
if let data = data {
print(try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)) // Prints nil
print(String(data: data, encoding: String.Encoding.utf8)) // Prints the site's HTML
}
}.resume()
}
I fail to see where the issue is. I've also tried not setting the HTTP headers but that makes no difference. Anyone got any ideas?
It seems like not setting the HTTP header fields and using a string literal instead of a Dictionary as HTTP body data did it for me.
For anyone interested this is the code that now receives the expected response:
guard let url = URL(string: "http://api.foo.com/login.php?"),
let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics),
let encodedPassword = password.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics) else {
if let delegate = self.delegate {
delegate.viewModelDidRejectLogin(self)
}
return
}
let httpBodyString = "user=\(encodedUsername)&password=\(encodedPassword)&client=ios&version=5"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = httpBodyString.data(using: String.Encoding.utf8)
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
print(error)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String : AnyObject] {
self.readLoginResponse(json)
}
} catch {
print(error)
}
}.resume()

IOS url request issue

I want to send mobile number and password to the server in the ios app. Backend team has given postman API like below image.
Success when sent as form-data
Below Swift URL request failing, What I'm doing wrong here?
func sendReq() {
let Url = String(format: "http://xxxxxxx/mobile/request_otp")
guard let serviceUrl = URL(string: Url) else { return }
let parameterDictionary = ["mobile_number" : "xxxxxxxxxx", "password" : "12345678"]
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.cachePolicy = .useProtocolCachePolicy
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// params dict as data
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: []) else {
return
}
request.httpBody = httpBody
// session
let session = URLSession.shared
//data task
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
}
catch {
print(error)
}
}
}.resume()
}
But above API call throwing error like
{
error = TRUE;
message = "All fields Required!";
}
Set the Content-Type HTTP header:
request.allHTTPHeaderFields = ["Content-Type": "application/json"]
This way you inform the server that you are sending JSON.
Can you try:
{\"mobile_number\":xxxxxxxxxx,\"password\":12345678}
and select Application/Json instead of text.

Receive POST request from Swift in Node.js

I am trying to receive and process a POST request being sent from my iOS app to my Node.js web server. The server responds with HTTP Error 502 whenever I try to send this POST request. Could you please look at my code below and see what is wrong with it? Thank you!
Node.js Code
app.post('/applogin', function(req, res) {
var parsedBody = JSON.parse(req.body);
console.log(parsedBody)
});
Swift Code (POST function)
func httpPost(jsonData: Data) {
if !jsonData.isEmpty {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
URLSession.shared.getAllTasks { (openTasks: [URLSessionTask]) in
NSLog("open tasks: \(openTasks)")
}
let task = URLSession.shared.dataTask(with: request, completionHandler: { (responseData: Data?, response: URLResponse?, error: Error?) in
NSLog("\(response)")
})
task.resume()
}
}
Swift Code (sending of the POST request)
#IBAction func onClick(_ sender: Any) {
let username = Username.text
let password = Password.text
var dataString = "username: \(username), password: \(password)"
let data = dataString.data(using: .utf8)
httpPost(jsonData: data!)
}
Thanks in advance!
You have to send a json instead dataString, and you have to set the "Content Type" header with value "application/json"
Swift 2
let request = NSMutableURLRequest(URL: requestUrl)
request.HTTPMethod = "POST"
let params = ["username" : username, "password" : password] as Dictionary<String, AnyObject>
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options:NSJSONWritingOptions.PrettyPrinted)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
Many answers they don't mention that we need to set header for the request from Swift side before sending to the backend otherwise it'll be a string in a wrong format that we can't use JSON.parse, here's what I firgured out (NOTE the IMPORTANT line):
let json = [
"email": emailTextField.text
]
let jsonData = try! JSONSerialization.data(withJSONObject: json)
let url = URL(string: BASE_URL + "/auth/register")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
//IMPORTANT
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
And in your NodeJS with Express just call req.body and you're done
Try this:
app.post('/applogin', function(req, res) {
var parsedBody = JSON.parse(req.body);
console.log(parsedBody)
res.send("Request received")
});

Access Magento Rest API in iOS - swift 3.0

I want to access the magenta REST API in my iOS application.
Following is my code to access the API:
func getCustomerTokenusingURLSEssion(){
let url = URL(string: "HTTPURL")!
var urlRequest = URLRequest(
url: url,
cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 10.0 * 1000)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let json1: [String: Any] = [
"username": "xyz#gmail.com",
"password":"xyz12345"]
let jsonData = try? JSONSerialization.data(withJSONObject: json1, options: .prettyPrinted)
urlRequest.httpBody = jsonData
let config = URLSessionConfiguration.default
let urlsession = URLSession(configuration: config)
let task = urlsession.dataTask(with: urlRequest){ (data, response, error) -> Void in
print("response from server: \(response)")
guard error == nil else {
print("Error while fetching remote rooms: \(error)")
return
}
guard let data = data,
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else {
print("Nil data received from fetchAllRooms service ")
return
}
print("JSON \(json)")
}
task.resume()
}
But I'm getting error message form the server as follow:
["message": Server cannot understand Content-Type HTTP header media type application/x-www-form-urlencoded]
Please help!
Thanks!
Here's working example of token-based authentication from iOS to magento2 using swift:
func restApiAuthorize(completionBlock: #escaping (String) -> Void) {
// Prepare json data
let json: [String: Any] = ["username": “yourusername”,
"password": “yourpassowrd”]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
// Create post request
let url = URL(string: "http://yourmagentodomain.com/index.php/rest/V1/integration/customer/token")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("\(jsonData!.count)", forHTTPHeaderField: "Content-Length")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// Insert json data to the request
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
// 1: Check HTTP Response for successful GET request
guard let httpResponse = response as? HTTPURLResponse
else {
print("error: not a valid http response")
return
}
print(httpResponse.statusCode)
switch (httpResponse.statusCode)
{
case 200:
let responseData = String(data: data, encoding: String.Encoding.utf8)!
print ("responseData: \(responseData)")
completionBlock(responseData)
default:
print("POST request got response \(httpResponse.statusCode)")
}
}
task.resume()
}
And usage is like that:
restApiAuthorize() { (output) in
// token data, I found it important to remove quotes otherwise token contains extra quotes in the end and beginning of string
let userToken = output.replacingOccurrences(of: "\"", with: "")
print ("userToken \(userToken)")
}
you can then write your userToken to userDefaults and make feature api calls.
Best Guest you forgot to set your Content-Type, so add this:
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")

Add POST,PUT,DELETE request class for swift

I have create a client service class to make call GET request from web api. I tried to extended but have more web method POST,PUT,Delete.I don't find good example in how to create POST,PUT,Delete using swift closure.I just want to ask how to add POST,PUT,Delete to client service?
import Foundation
class ClientService{
func getClients(searchstring:String,pageNumber:Int,callBack:(NSArray)->()){
request("\(_settings.baseUrl)Client/\(searchstring)/\(String(pageNumber))/rrn/brns", callBack: callBack)
}
func request(url:String,callBack:(NSArray)->()){
let nsURL = NSURL(string:url);
let task = NSURLSession.sharedSession().dataTaskWithURL(nsURL!){
(data,response,error) in
do {
let response = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
callBack(response)
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
}
task.resume()
}
init(){
self._settings = Settings();
}
var _settings:Settings!;
}
You are on the right track. I make a separate function for get, post, put, delete etc. But you could make them in a one function if you want.
Bear in mind, this code is just to illustrate how to do it. You will need to modify it for your needs.
func request(url:String, method: String, params: [String: String], completion: ([AnyObject])->() ){
if let nsURL = NSURL(string:url) {
let request = NSMutableURLRequest(URL: nsURL)
if method == "POST" {
// convert key, value pairs into param string
postString = params.map { "\($0.0)=\($0.1)" }.joinWithSeparator("&")
request.HTTPMethod = "POST"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
}
else if method == "GET" {
postString = params.map { "\($0.0)=\($0.1)" }.joinWithSeparator("&")
request.HTTPMethod = "GET"
}
else if method == "PUT" {
putString = params.map { "\($0.0)=\($0.1)" }.joinWithSeparator("&")
request.HTTPMethod = "PUT"
request.HTTPBody = putString.dataUsingEncoding(NSUTF8StringEncoding)
}
// Add other verbs here
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, error) in
do {
// what happens if error is not nil?
// That means something went wrong.
// Make sure there really is some data
if let data = data {
let response = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)
completion(response)
}
else {
// Data is nil.
}
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
}
task.resume()
}
else{
// Could not make url. Is the url bad?
// You could call the completion handler (callback) here with some value indicating an error
}
}
Call it like this:
request("http://somedomain.etc", "POST", ["key1" : "value1", "key2", "values2"]) {
(result) in
// Handle result here.
}
You will note that I eliminated NSArray. [AnyObject] is the Swift way to do this.
I recommend that you add some sort of error indicator in the completion handler. That would let you detect that something went wrong and handle it.
Be very cautious when using ! to unwrap variables. This is the most common reason for apps crashing.
i use for mes projects Alamofire (Elegant HTTP Networking in Swift), and i love it
so example how to use POST
let parameters = [
"foo": "bar",
"baz": ["a", 1],
"qux": [
"x": 1,
"y": 2,
"z": 3
]
]
Alamofire.request(.POST, "https://httpbin.org/post", parameters: parameters)
// HTTP body: foo=bar&baz[]=a&baz[]=1&qux[x]=1&qux[y]=2&qux[z]=3
and here how to use Delete
Alamofire.request(.DELETE, "https://httpbin.org/delete")
go to documentation is very good
https://github.com/Alamofire/Alamofire
and if you want use swift without framework
this is example how to use POST
var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:4567/login"))
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params = ["username":"jameson", "password":"password"] as Dictionary<String, String>
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
var success = parseJSON["success"] as? Int
println("Succes: \(success)")
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
Instead of using dataTaskWithUrl, you could create an HTTP request like this:
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = jsonData
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(String (jsonData?.length), forHTTPHeaderField: "Content-Length")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { data, res, error in
// etc etc
Everything else in your example above would be the same. You'd have to provide the json data, of course. For that, you could do something like this:
let data: [String: AnyObject] = ["nameValue": dataValue]
var jsonData: NSData? = nil
do {
jsonData = try NSJSONSerialization.dataWithJSONObject(data, options: NSJSONWritingOptions(rawValue: 0))
} catch {
// some error serializing
}
Swift 4 version (I think):
func restRequest(url:String, method: String, params: [String: String], completion: #escaping ([AnyObject])->() ){
if let nsURL = NSURL(string:url) {
let request = NSMutableURLRequest(url: nsURL as URL)
if method == "POST" {
// convert key, value pairs into param string
let postString = params.map { "\($0.0)=\($0.1)" }.joined(separator: "&")
request.httpMethod = "POST"
request.httpBody = postString.data(using: String.Encoding.utf8)
}
else if method == "GET" {
let postString = params.map { "\($0.0)=\($0.1)" }.joined(separator: "&")
request.httpMethod = "GET"
}
else if method == "PUT" {
let putString = params.map { "\($0.0)=\($0.1)" }.joined(separator: "&")
request.httpMethod = "PUT"
request.httpBody = putString.data(using: String.Encoding.utf8)
}
// Add other verbs here
let task = URLSession.shared.dataTask(with: request as URLRequest) {
(data, response, error) in
do {
// what happens if error is not nil?
// That means something went wrong.
// Make sure there really is some data
if let data = data {
let response = try JSONSerialization.JSONObjectWithData(data, options: JSONSerialization.ReadingOptions.MutableContainers)
completion(response)
}
else {
// Data is nil.
}
} catch let error as NSError {
print("json error: \(error.localizedDescription)")
}
}
task.resume()
}
else{
// Could not make url. Is the url bad?
// You could call the completion handler (callback) here with some value indicating an error
}
}

Resources