Backend is unable to find headers when sending request from IOS application - ios

i am able to hit api from postman, but when i hit from IOS application it always throws an error that "A valid API key is required to use this service."
API Endpoint: https://connect.ttfnow.com/api/url/add
Headers: key= "Authorization", value= "Token BDifVxMyHSlB"
Method: POST
Body Raw Json: {url: "www.google.com"}
I used postman code for swift but it did not worked in application.
I tried with url session and alamofire but nothing worked.
let headers: HTTPHeaders = ["Content-Type": "application/json",
"Authorization": "Token BDifVxMyHSlB"]
let params: [String: Any] = ["url": "www.google.com"]
AF.request(URL(string: "https://connect.ttfnow.com/api/url/add")!, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
print(response)
}
Here is code from url session
var semaphore = DispatchSemaphore (value: 0)
let parameters = "{\n \"url\": \"www.google.com\"\n}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://connect.ttfnow.com/api/url/add")!,timeoutInterval: Double.infinity)
request.addValue("Token BDifVxMyHSlB", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("PHPSESSID=c6mirs7a3qspcq86hhdvo2o2po", forHTTPHeaderField: "Cookie")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
here is image from postman
Header tab of postman

Related

Convert httpBody for x-www-urlencoded

I'm doing a POST call to server but Alamofire always send the body as a JSON and not as a Form URL Encoded, I do know that in oder to encode the body I have to insert data(using: .utf8, allowLossyConversion: false), but I don't know where.
How can I fix my code?
This is my actual code:
func asURLRequest() throws -> URLRequest {
let url = try DBank.StagingServer.baseUrl.asURL()
var urlRequest = URLRequest(url: url.appendingPathComponent(path))
// HTTP Method
urlRequest.httpMethod = method.rawValue
// Common Headers
headers.forEach { (field, value) in
urlRequest.setValue(value, forHTTPHeaderField: field)
}
// Parameters
if let parameters = parameters {
do {
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
} catch {
throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
}
}
I'm guessing you have response handler like below:
Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding(destination: .queryString), headers: headers)
.validate(statusCode: 200..<300)
.responseString { response in
//response.result.value will contain http response from your post call
}
With the result from this response you would set:
UserDefaults.standard.set("<result>", forKey: "<token>")

Http POST request in swift to send an email via Mailjet

I'm trying to send an email with the Mailjet API v3 with a http post request but I'm getting an error 400.
I used the exact same body with success in Javascript, but I guess the error 400 is related with it...
Any ideas ?
var recipients = [Any]()
recipients.append(["Email": "email#gmail.com"])
var body: [String: Any] = [
"FromEmail": "anEmail#gmail.com",
"FromName": "Me",
"Subject": "YEEES",
"Text-part": "Greetings from IOS ;)",
"Recipients": recipients
]
var request = URLRequest(url: self.apiURL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Authorization", forHTTPHeaderField: "Basic <keysInBase64>")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: body, options: [])
}
catch {
print("error during JSON serialization")
dump(error)
return
}
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
print(error)
print(response)
print(data)
})
task.resume()
Headers was wrong...
I was doing :
request.setValue("Authorization", forHTTPHeaderField: "Basic <keysInBase64>")
Instead of :
request.setValue("Basic <keysInBase64>", forHTTPHeaderField: "Authorization")
Using the Charles Proxy as suggested by #LouFranco, I was able to find the mistake.

Why Authorization header gets removed in iOS PATCH requests?

there. I got a very strange problem. The thing is that when i'm trying to send PATCH requests server says that no Authorization header contains token. The same for PUT request.Tried to sniff and found out that no Authorization header is sent at all. While any other types of request contain Authorization header. First thought its Alamofire framework specific problem, but using NSURLConnection requests and NSURLSession tasks gave me the same: NO AUTHORIZATION HEADER IS SENT!
Here is my code used for Alamofire:
Alamofire.request(.PATCH, path, parameters: ["email":"new#mail.com"], encoding: .JSON, headers: ["Authorization":"token \ ((User.sharedUser().token)!)"]).validate().responseJSON { (response) in
if response.response?.statusCode == 200{
print("success")
}else{
print("Error")
}
}
and here is code with NSURLConnection:
let request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
request.HTTPMethod = "PATCH"
request.addValue("\(token)", forHTTPHeaderField: "authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do{
let bodyData = try NSJSONSerialization.dataWithJSONObject(["email":"nuv#gmail.com"], options: [])
request.HTTPBody = bodyData
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue())
{
(response, data, error) in
if let mdata = data {
let contents = NSString(data:data, encoding:NSUTF8StringEncoding)
print(contents)
} else {
print(error?.localizedDescription)
}
}
}catch{
print("failed serialization")
}
IIRC, the Authorization header is one of those headers that NSURLSession reserves for its own purposes, and may overwrite with its own values—particularly if you're sending something that looks like normal HTTP authentication.
Can you send an X-Authorization header instead?
Anyone who is looking for Alamofire 5(AF 5) solution here's the solution:
let headers: [String:String] = [...]
let params: [String: Any] = [...]
let url = URL(...)
let redirector = Redirector(behavior: Redirector.Behavior.modify({ (task, urlRequest, resp) in
var urlRequest = urlRequest
headers.forEach { header in
urlRequest.addValue(header.value, forHTTPHeaderField: header.key)
}
return urlRequest
}))
//use desired request func of alamofire and your desired enconding
AF.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
//handleDataResponse...
}.redirect(using: redirector)

How to send a HTTP POST like this in Swift?

{
"appId":"YOUR_APP_ID",
"appKey":"YOU_APP_KEY",
"queries":{
"item_name":"Kids Fries",
"brand_name":"McDonalds"
}
}
I know how to handle the first two items(appId,appKey) in postString, but I don't know what the format be for "queries", I tried the following, it did not work:
let request = NSMutableURLRequest(URL: url! )
request.HTTPMethod = "POST"
let postString = "appId=myId9&appKey=myKey&queries={item_name=burger&brand_name=McDonalds}"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
What Content-Type does the server expect?
You are showing application/json in the first part, but application/x-www-form-urlencoded in the second part.
If you need application/json, then
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let postString = "{\"appId\":\"myId\", \"appKey\":\"myKey\", \"queries\":{\"item_name\":\"Kids Fries\", \"brand_name\":\"McDonalds\"}}"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
If you really need application/x-www-form-urlencoded, then some guessing is involved. Why not try using the dot-syntax.
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let postString = "appId=myId&appKey=myKey&queries.item_name=burger&queries.brand_name=McDonalds"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
Have you tried Alamofire. Its really easy to do this in that.
All you have to do is do something like the following and it post;
let myParams = [
"key1": value1 ,
"key2": value2,
"key3": value3,
"Key4": value4
]
Alamofire.request(.POST, posturl, parameters: myParams, encoding: .JSON)
.authenticate(user: self.postUser, password: self.postPass)
.validate(statusCode: 200..<300)
.responseString { response in
print("Response String: \(response.result.value)")
if response.result.value != nil{
let rJ = response.result.value!
print("Response: " + rJ)
}else
{
print("Fail")
}
}
Hopes this helps. And Alamofire makes get request easier too.
You can also try this code with Alamofire
let parameters = [“Username”:”name”]
let headers = ["Content-Type":"application/json"]
Alamofire.request(.POST, “your URL here”, parameters: parameters, encoding: .JSON, headers: headers)
.responseJSON { response in
print("Response JSON: \(response.result.value)")
//--------------------
switch response.result {
case .Success:
self.successGetData(response.result.value!)
case .Failure(let error):
self.failedGetData()
print(error)
}
}

HTTP Request with Body using PATCH in Swift

I'm trying to send a Patch request with a serialized JSON Body.
For some reason the server is not able to receive the body properly. I have a feeling that there seems to be a problem with the PATCH method in combination with the http request body.
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
var URL = B2MFetcher.urlForBooking(event.unique, bookingID: booking.unique)
let request = NSMutableURLRequest(URL: URL)
request.HTTPMethod = "PATCH"
// Headers
println(token)
request.addValue(token, forHTTPHeaderField: "Authorization")
request.addValue("gzip, identity", forHTTPHeaderField: "Accept-Encoding")
// JSON Body
let bodyObject = [
"op": "cancel"
]
var jsonError: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(bodyObject, options: nil, error: &jsonError)
/* Start a new Task */
let task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData!, response : NSURLResponse!, error : NSError!) -> Void in
completion(data: data, response:response , error: error)
})
task.resume()
You could try to add a Content-Type header to the request:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
or use one of the other JSON Content-Type formats described here.
I tested it with an ExpressJS server and without the Content-Type header the server got an empty body, but with a Content-Type header it worked well.
in swift 3/4 :
let request = NSMutableURLRequest(url: NSURL(string: "http://XXX/xx/xxx/xx")! as URL)
request.httpMethod = "PATCH"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do{
let json: [String: Any] = ["status": "test"]
let jsonData = try? JSONSerialization.data(withJSONObject: json)
request.httpBody = jsonData
print("jsonData: ", String(data: request.httpBody!, encoding: .utf8) ?? "no body data")
} catch {
print("ERROR")
}
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error)")
completion(false)
return
}
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
completion(true)
return
}
task.resume()
Simple Way to use patch without using HTTPBody
If you want to just use patch, you just need to change the value of the name of a specific user then it will be like:
let myurl = URL(string: "https://gorest.co.in/public-api/users/"+"\(id)?"+"name=abc")!
var request = URLRequest(url:myurl)
request.addValue("Bearer yourAuthorizationToken",forHTTPHeaderField:"Authorization")
request.httpMethod = "PATCH"
let dataTask = URLSession.shared.dataTask(with: request)
dataTask.resume()
Note: here "id" will be userId

Resources