Send post request with bearer token and json body in Swift - json

I'm pretty new to swift and i tried to make a post request to a website, but couldn't come up with an working result, yet. All examples I found didn't work for me either.
I need to send a json body to https://mypostrequestdestination.com/api/
The json body only contains of one value
{State:1}
And the Header has to contain
{"Authorization": bearer "token"}
{"Accept":"application/json"}
{"Content-Type":"application/json"}
Hope someone can help me.
Thanks!

This one worked for me
let token = "here is the token"
let url = URL(string: "https://mypostrequestdestination.com/api/")!
// prepare json data
let json: [String: Any] = ["State": 1]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
// create post request
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue( "Bearer \(token)", forHTTPHeaderField: "Authorization")
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()

Related

Unable to Upload Image and add parameters with POST method multipart/form-data in Swift

Below is the URL requirement for this API: http://itaag-env-1.ap-south-1.elasticbeanstalk.com/editprofile/
according to this answer Upload image with multipart form-data iOS in Swift
I have tried below code, but i am unable to add parameters to POST Request and i am unable to call uploadImage method in viewdidload
Here is the code:
func uploadImage(paramName: String, fileName: String, image: UIImage) {
let url = URL(string: "http://itaag-env-1.ap-south-1.elasticbeanstalk.com/editprofile/")
let boundary = UUID().uuidString
let deviceId: String = "HardcodeDEVICEIDforiTaag222"
let headers = ["deviceid": "deviceId","userType": "personal","key": "5fe42fb3b54543a0bab5667cf96526f8"]
let parameters: [String: Any] = ["firstName":"Satish", "lastName":"Madhavarapu","gender":"male", "ageGroup":"40-50"]
let session = URLSession.shared
var urlRequest = URLRequest(url: url!)
urlRequest.httpMethod = "POST"
urlRequest.allHTTPHeaderFields = headers as! [String : String]
// Set Content-Type Header to multipart/form-data, this is equivalent to submitting form data with file upload in a web browser
// And the boundary is also set here
urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var data = Data()
// Add the image data to the raw http request data
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(paramName)\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
data.append("Content-Type: image/png\r\n\r\n".data(using: .utf8)!)
data.append(image.pngData()!)
data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
// Send a POST request to the URL, with the data we created earlier
session.uploadTask(with: urlRequest, from: data, completionHandler: { responseData, response, error in
if error == nil {
let jsonData = try? JSONSerialization.jsonObject(with: responseData!, options: .allowFragments)
if let json = jsonData as? [String: Any] {
print(json)
}
}
}).resume()
}
in the above code i am unable to add parameters let parameters: [String: Any] = ["firstName":"Satish", "lastName":"Madhavarapu","gender":"male", "ageGroup":"40-50"] to urlRequest
And How to call uploadImage in viewDidLoad
Please help me with code

MVC Json Parsing - Swift

I get json output from the MVC project. You can see this output in the image below. But I cannot draw this output on the swift side. For example, I sent the value 6 to the id parameter and got the output in postman. Likewise, how can I pull this data on the swift side?
#objc func gorselCEK(){
let url = URL(string: ".../MobilService/KategoriGorsel/")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "id=\(6)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
return
}
do {
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: AnyObject]
if let json = try JSONSerialization.jsonObject(with: data) as? [String: String],
let sifre = json[""] {
//Doesn't go in here
}
} catch let parseError {
print("parsing error: \(parseError)")
let responseString = String(data: data, encoding: .utf8)
print("raw response: \(responseString)")
}
}
task.resume()
}
In the postman, it is GET request and in Swift, you're trying to make a POST request.
Change request method to GET
request.httpMethod = "GET"
Update URL with QueryItems
var urlComponent = URLComponents(string:".../MobilService/KategoriGorsel/")!
url.queryItems = [
URLQueryItem(name: "id", value: "6")
]
//Request
var request = URLRequest(url: urlComponent.url)
request.httpMethod = "GET"
No need to set httpBody

HTTP Authentication request with Campaign Monitor in Swift

I am trying to post user data to Campaign Monitor when they sign up in my app. Can anyone help me add the authorisation to the request. I currently get this error:
Optional("{\"Code\":50,\"Message\":\"Must supply a valid HTTP Basic
Authorization header\"}")
my code:
let parameters = [ "FirstName1": "test",
"SecondName": "test",
"email": "test#test.com"
]
let clientID = "52bb93ac4d9a3f261abcda0123456789"
let url = URL(string: "https://api.createsend.com/api/v3.2/clients.json")!
var request = URLRequest(url: url)
request.httpMethod = "Post"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
// add the API Key to the request / security
request.setValue(clientID, forHTTPHeaderField: "username") // IS THIS RIGHT??
// THiS WAS HOW I CREATED CORRECT AUTHORIZATION
let APIKey = "0069b38c27b3e44de0234567891011"
let listID = "5e61fde130969d561dc0234567891011"
let url = URL(string: "https://api.createsend.com/api/v3.2/subscribers/\(listID).json")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// add the API Key to the request / security
let loginString = "\(APIKey)"
let loginData = loginString.data(using: String.Encoding.utf8)
let base64LoginString = loginData!.base64EncodedString()
request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
// THEN CAN SET UP THE SESSION
let session = URLSession(configuration: .default)
let task = session.dataTask(with: request) {
(data, response, error) in
if error != nil {
print("Error is: \(String(describing: error))")
}
if let response = response {
let nsHTTPResponse = response as! HTTPURLResponse
let statusCode = nsHTTPResponse.statusCode
print("status code = \(statusCode)")
}
if let data = data {
let postResponse = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: postResponse))")
}
}
task.resume()
In this line:
// add the API Key to the request / security
request.setValue(clientID, forHTTPHeaderField: "username") // IS THIS RIGHT??
It's not correct, even they told you why. You need a Basic Auth Header
For POST requests in Swift, generally you have to set the following:
request.setValue("Basic " + clientID, forHTTPHeaderField: "Authorization") // is clientID your access token?
Good luck

How to make this POST request with different objects?

Overview:
I am trying to make a POST request, which I have done before with only strings. This time, I have a few variables, being: String, Int, and Bool.
Error:
Cannot assign value of type [String : Any] to type Data
Line causing the error:
request.httpBody = paramToSend
Question:
How to convert a Dictionary into Data ?
Complete Code:
func sendComplimentAPI (message: String, recipient: Int, isPublic: Bool) {
let url = URL(string: "https://complimentsapi.herokuapp.com/compliments/send/")
let session = URLSession.shared
let preferences = UserDefaults.standard
let request = NSMutableURLRequest(url: url!)
request.addValue("\(preferences.object(forKey: "token") as! String)", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
let paramToSend = ["message":message,"recipient":recipient,"is_public":isPublic] as [String : Any]
request.httpBody = paramToSend
let task = session.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) in
guard let _:Data = data else {return}
let json:Any?
do{json = try JSONSerialization.jsonObject(with: data!, options: [])}
catch {return}
guard let server_response = json as? NSDictionary else {return}
if let session_data = server_response["id"] as? String {
print("worked")
//do something
/*DispatchQueue.main.async (
execute:
)*/
} else {
print("error")
}
})
task.resume()
}
EDIT:
I have tried this new code and it is still not posting to the server. I am attaching what I changed and also writing what the console shows for the two prints I have it do.
let paramToSend = ["message":writeTextField.text!,"recipient":1,"is_public":isPrivate] as [String : Any] //messageString + recipientString + isPublicString
do {
var serialized = try JSONSerialization.data(withJSONObject: paramToSend, options: .prettyPrinted)
print(serialized)
request.httpBody = serialized
print(request.httpBody)
} catch {
print("found a problem")
}
The console returns (for serialized and then the HTTP body):
113 bytes
Optional(113 bytes)
Is that optional causing the problem? How do I fix it?
To convert Dictionary to Data, use JSONSerialization.data:
Solution:
JSONSerialization.data(withJSONObject: paramToSend, options: .prettyPrinted)
Check the request:
Print the request and see if it matches your expectation
Reading the response:
//Check if there is any error (check if error != nil)
//Examine the response
let statusCode = (response as? HTTPURLResponse)?.statusCode
let statusCodeDescription = (response as? HTTPURLResponse)?.localizedString(forStatusCode: httpResponse.statusCode)
//Check Data
if let data = data {
let dataString = String(data: data, encoding: String.Encoding.utf8)
}
It turns out I needed to add a simple additional header to get the whole thing to work.
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
This is probably why it was not understanding the dictionary I was sending it

Swfit 4 JSON adding custom header

How can I add custom header while sending GET request on server.
I have tried
var request = URLRequest(url: URL(string: URL)!)
request.httpMethod = "GET"
// request.addValue("2", forHTTPHeaderField: "x-api-version")
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Accept")
P.S I am beginner so if there is any mistake please point it out and help me to improve. Thank you in advance.
If your purpose is to authenticate to the API using a token, you set the wrong format for the Authorization header. Token authorization is also called "bearer authorization", the format is below:
let url = URL(string: "https://httpbin.org/get")!
let token = "abcdef"
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else { print(error!); return }
guard let data = data else { print("No data"); return }
if let str = String(data: data, encoding: .utf8) {
print(str)
}
}.resume()
You don't need the Content-Type header since a GET request has no body content.
Try below code:
func setHeader() -> [String : String] {
let dictionary = [
"Accept":"application/json",
"Content-Type":"application/json",
"Authorization": "your_authtoken"
// more headers here
]
return dictionary
}
// calling
request(endPoint, method: .post, parameters: params, encoding:JSONEncoding.default, headers: setHeader())