Getting error In posting Data in swift - ios

I am sending the data using post method like this
let login = ["user_name":usernameTextField.text,"password":passwordTextField.text]
//["user":"ords_user#gmail.com", "pass":"ords_password"]
let url = NSURL(string: "http://localhost:8300")!
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url)
do {
// JSON all the things
let auth = try NSJSONSerialization.dataWithJSONObject(login, options: .PrettyPrinted)
// Set the request content type to JSON
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
// The magic...set the HTTP request method to POST
request.HTTPMethod = "POST"
// Add the JSON serialized login data to the body
request.HTTPBody = auth
// Create the task that will send our login request (asynchronously)
let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
// Do something with the HTTP response
print("Got response \(response) with error \(error)")
print("Done.")
})
// Start the task on a background thread
task.resume()
} catch {
// Handle your errors folks...
print("Error")
}
But I am getting the error message like
Argument type '[String : String?]' does not conform to expected type ‘AnyObject’
If I give the direct string it is accepting. If I am giving dynamically using the TextFields it is not coming. I don’t know what is the mistake I have done.
Can anyone Please help to solve this issue?
Thanks in advance.

I think your issue is that you are putting optional strings into the dictionary.
Try doing this:
guard
let username = usernameTextField.text,
let password = passwordTextField.text else {
return print("Need username & password")
}
let login = ["user_name": username,"password": password]
...

UITextField's text property returns an optional value, so compiler can't convert it to AnyObject.
You have to unwrap optionals before.

Try this
let login = ["user_name":usernameTextField.text,"password":passwordTextField.text] as Dictionary<String, AnyObject>

Related

How to pass bearer token to make Yelp API call with URLSessoin

U P D A T E D... The function with what works!
I would like to incorporate the yelp api into an app but can't successfully pass my authorization token on the URL string. Do I need to do something to connect the URLRequest to the URLSessoin call and its not using the header? Maybe the key value pairs is wrong? The below function returns:
error = {
code = "TOKEN_MISSING";
description = "An access token must be supplied in order to use this endpoint.";
};
I was able to use postman to get the yelp API call working, but only by clicking the "Header" section on postman and putting in Bearer and then my yelp key. I googled around a bit and found some links that indicate that you can add a header to the URLSession that I assume would work the way postman does but I haven't been able to get it to work.
I know there are some githubs with yelp API repos but I am trying to not install a large set of code that I don't understand into my app, when all I want is the JSON that I can see is coming through on postman. Can anyone help me understand how I would edit code similar to the Here example below so that I can get the Authorization/Bearer that yelp requires?
func getYelp() {
let appSecret = "Bearer <YELP APIKEY>"
let link = "https://api.yelp.com/v3/businesses/search?latitude=37.786882&longitude=-122.399972"
if let url = URL(string: link) {
// Set headers
var request = URLRequest(url: url)
request.setValue("Accept-Language", forHTTPHeaderField: "en-us")
request.setValue(appSecret, forHTTPHeaderField: "Authorization")
print("Attempting to get places around location from Yelp")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!)
} else {
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject // Added "as anyObject" to fix syntax error in Xcode 8 Beta 6
print("Printing all JSON/n/n//n--------------------------")
print(jsonResult)
print("Printing from results/n/n//n--------------------------")
if let description = ((jsonResult["search"] as? NSDictionary)?["context"] as? NSDictionary)?["href"] as? String {
} else {
print("JSON pull failed/n/n//n--------------------------")
}
} catch {
print("JSON Processing Failed/n/n//n--------------------------")
}
}
}
}
task.resume()
} else {
resultLabel.text = "Couldn't get results from Here"
}
}
You're mixing up between the headers and the url, you need to set your headers correctly
if let url = URL(string: "https://places.cit.api.here.com/places/v1/discover/around?at=37.776169%2C-122.421267&app_id=\(app_id)&app_code=\(app_code)") {
var request = URLRequest(url: url)
// Set headers
request.setValue("Accept-Language", forHTTPHeaderField: "en-us")
request.setValue("Authorization", forHTTPHeaderField: "Bearer " + token // Token here)
print("Attempting to get places around location")
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
// ...
Lets say you have an api with "https://google.com" (this is just an example with fake keys)
and an api key that is "ApiKey: 92927839238293d92d98d98d92".
You would then take this information and do this.
let uri = URL(string:"https://google.com")
if let unwrappedURL = uri {
var request = URLRequest(url: unwrappedURL)request.addValue("92927839238293d92d98d98d92", forHTTPHeaderField: "ApiKey")
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
// you should put in error handling code, too
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
// HERE'S WHERE YOUR DATA IS
print(json)
} catch {
print(error.localizedDescription)
}
}
}
dataTask.resume()
}
Please remember that you would replace the google.com with your GET address and the APIKey header with your own api key values.
Also, this will print out all the JSON like in PostMan.
If this works for you, then I also have a link on accessing the JSON Objects.

Swift POST request sends an empty body

Here's the code:
func makePOSTCall(endpoint: String, languageName: String) {
guard let url = URL(string: endpoint) else {
print("Could not create URL.")
return
}
let requestLang: [String: Any] = ["name": languageName]
let requestBody = try? JSONSerialization.data(withJSONObject: requestLang)
var urlRequest = URLRequest(url: url)
urlRequest.httpBody = requestBody
urlRequest.httpMethod = "POST"
let session = URLSession.shared
let task = session.dataTask(with: urlRequest) {
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()
}
This sends a {"name": "Go"} JSON dictionary to Flask. Flask is supposed to append the language name to an array and return the full array in the response. Now, this works when I send the request manually, so it's not Flask's error. But when I send the above from iOS, I get request.json == None in the flask console. Clearly, I'm sending an empty body, but I shouldn't be. Any idea where I went wrong?
I call the function as
#IBAction func pressedMakePOSTCall(_ sender: UIButton) {
makePOSTCall(endpoint: "http://127.0.0.1:5000/lang", languageName: "Go")
}
I tried adding a trailing slash, just get a 404 in the console. The only question similar to mine that I've found is this: How to make HTTP Post request with JSON body in Swift and my code is basically identical.
#weissja19 was correct, I needed to set content type to application/json. Adding
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
fixed the error. Now the code works as I expected.
P.S. I couldn't catch it because I use the app Paw for testing, which sets content type automatically.
You might want to do it manually:
urlRequest.httpBody = "name=\(languageName)".data(using: .utf8)
Use JSONSerialization will make your POST body like {"name":"abc"} which might not be supported by your server

How to get userID from JSON response while JSON text did not start with array or object and option to allow fragments not set

I got json response from server like this:
"{\"userID\":\"dkjagfhaghdalgalg\"}"
I try to get that userID with this:
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, error) -> Void in
if let unwrappedData = data {
do {
let userIDDictionary:NSDictionary = try NSJSONSerialization.JSONObjectWithData(unwrappedData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
print("userIDDictionary:\(userIDDictionary)")
//let userID:String = userIDDictionary["userID"] as! String
//print("userID:\(userID)")
print("data:\(data)")
print("response:\(response)")
print("error:\(error)")
} catch {
print("Failed to get userID: \(error)")
}
}
}
but the response is
Failed to get userID: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set. UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}".
How to get userID with json response like that?
update: I try to get with anyobject but still did not get that json string to change to dictionary.
let bodyStr = "test={ \"email\" : \"\(username)\", \"password\" : \"\(password)\" }"
let myURL = NSURL(string: Constant.getSignInEmail())!
let request = NSMutableURLRequest(URL: myURL)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPBody = bodyStr.dataUsingEncoding(NSUTF8StringEncoding)!
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, error) -> Void in
if let unwrappedData = data {
do {
let json:AnyObject! = try NSJSONSerialization.JSONObjectWithData(unwrappedData, options: NSJSONReadingOptions.MutableContainers) as! AnyObject
print("json:\(json)")
//let userID:String = userIDDictionary["userID"] as! String
//print("userID:\(userID)")
} catch {
print("Failed to get userID: \(error)")
}
}
}
Try with try with NSJSONReadingOptions.AllowFragments in json reading options
I think this is a case of confusion between the data that you are receiving and the way they are displayed. Either on your side, or on the server side. Try to tell us exactly what the server is sending, byte for byte.
What you have got there is a string containing JSON. Not JSON, but a string containing JSON. Which is not the same. Just like a bottle of beer is not made of beer, but of glass.
If this is indeed what you are receiving, then you should first kick the guys writing the server code. If that doesn't help, then read what the "fragment" option does; this will give you a string, then you extract the bytes, and throw the bytes into a JSON parser.
Two way you can resolve.
Check your Webservice format and correct it as {"key":"value","key":"value"}
or else you have to Convert NSData to NSString.
Using String(data:, encoding:.utf8)
then format the string file with reduction '\'
then again convert it to NSData type then Call JSONSerialization.
Actually this is NSASCIIStringEncoding.
For help, I created a program.
Please just copy/paste and run it. You will find your answer.
import Foundation
let string = "{\"userID\":\"dkjagfhaghdalgalg\"}"
let unwrappedData: NSData = string.dataUsingEncoding(NSASCIIStringEncoding)!
do {
let userIDDictionary:NSDictionary = try NSJSONSerialization.JSONObjectWithData(unwrappedData, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
let userid = userIDDictionary.valueForKey("userID")
print("userid:\(userid!)")
} catch {
print("Failed to get userID: \(error)")
}

Posting to a secure API with swift

I'm trying to post to an API secured with a key (MailGun) with swift but it appears that my key is never utilized as I receive a Forbidden 401 error (Unauthorized - No valid API key provided) according to https://documentation.mailgun.com/api-intro.html#errors
I've verified the URL and key are correct by posting using curl, but I am unable to figure out why my key is not used here. I'm hoping someone can point in the right direction as to why this isn't authenticating correctly
My code is as such but I have replaced all the personal info with <>:
// Email the FBO with desired information
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.mailgun.net/v3/<My Domain>/messages")!)
request.HTTPMethod = "POST"
let data = "from: Excited User <scheduler#<mg.mydomain.com>>&to: [bar#example.com,<my email>]&subject:Hello&text:Testinggsome Mailgun awesomness!"
request.HTTPBody = data.dataUsingEncoding(NSASCIIStringEncoding)
request.setValue("key-<my key>", 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()
Update:
Banged away at it for a few hours and I still can't get my head around it. Maybe I'm not exactly sure what you mean? I can successfully get a response with curl by using:
curl -s --user 'api:key-<my personal key>' https://api.mailgun.net/v3/mg.<my domain>.com/messages -F from='Reservation Scheduler <scheduler#mg.<my domain>.com>' -F to=reservations#<my domain>.com -F subject='Curl Test' -F text='Test from terminal'
I tried inputting it explicitly like so:
request.setValue("api", forHTTPHeaderField: "username")
request.setValue("key-<my key>", forHTTPHeaderField: "password")
It looks to me like the basic auth credentials are never sent? How can I be sure that the fields are "user" and "password"?
After verifying my header appeared to be missing the authentication section of the header I was 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!

How to send json object in swift without "key - value" pair format

Hey so I have to send a a token string to the Django-server and it only accepts one string. I am trying to use alamo fire to do this, however I cant send a key-value pair to resolve this problem. Is there an alternative solution for this. I am new IOS developer and this is my first project and I am new to the community. Thank you.
Convert your dictionary into a JSON string and ship it off that way:
func jsonStringify(data: AnyObject) -> NSData? {
var error: NSError?
if let json = NSJSONSerialization.dataWithJSONObject(
data,
options: NSJSONWritingOptions(0),
error: &error
) {
return json
} else {
return nil
}
}
Depending on how you need to send the token (POST vs GET vs HTTP Body vs Query String)... you might need to change the below. But it should get you started with NSURLSession. This will send the token 189E23FL2 to the server with POST as a HTTP Body parameter.
let url = NSURL(string: "http://some-server/endpoint")
var request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.HTTPBody = "189E23FL2".dataUsingEncoding(NSUTF8StringEncoding)
// if you need a csrf token, add something like this as well:
// request.addValue("the-csrf-token", forHTTPHeaderField: "X-CSRFToken")
var sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: sessionConfiguration)
var task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData!, response : NSURLResponse!, error : NSError!) -> Void in
if (error == nil) {
println("Done!")
} else {
println("Errorororororor")
}
})
// start the task
task.resume()

Resources