Http POST request in swift to send an email via Mailjet - ios

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.

Related

How to access twitter filter search stream api on ios

This is the approach I am using to get the tweets via twitter new v2 filter search API after getting the bearer token.
static func callFilterSearch() {
let Url = String(format: "https://api.twitter.com/2/tweets/search/stream?place.fields=contained_within&user.fields=location&tweet.fields=geo")
guard let serviceUrl = URL(string: Url) else { return }
var request = URLRequest(url: serviceUrl)
request.httpMethod = "GET"
request.setValue("Bearer MY BEARER TOKEN", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("gzip, deflate, br", forHTTPHeaderField: "Accept-Encoding")
request.setValue("keep-alive", forHTTPHeaderField: "Connection")
request.setValue("*/*", forHTTPHeaderField: "Accept")
request.setValue("v2FilteredStreamPython", forHTTPHeaderField: "User-Agent")
let sessionConfig = URLSessionConfiguration.default
sessionConfig.networkServiceType = .responsiveData
let session = URLSession(configuration: sessionConfig)
session.dataTask(with: request) { (data, response, error) in
if let data = data {
do {
let teamJSON = try JSONSerialization.jsonObject(with: data, options: [.allowFragments, .fragmentsAllowed, .mutableContainers, .mutableLeaves])
print("teamJSON: \(teamJSON)")
} catch let error {
print("error: \(error)")
}
}
}.resume()
}
Unfortunately I am not successful in getting the tweets this way. However the python client that twitter has put in github repo seems to work just fine and is spewing tweets as expected.
Please help me out here

Posting a String array to an API via JSON body in Swift

I am trying to upload a string array to the Edamam API that uses the data from my local database. For the API, I need to post an array of strings with a label "ingr" so that it would recognize it. I should be able to enter the "\(mass) grams \(name)" of each ingredient and get a response that would analyze the macronutrients of said ingredient. The code I'm using:
API Config:
func getData(strURL: String, dictParam: Dictionary<String, Any>, completion: #escaping(Dictionary<String, AnyObject>)->()) {
var request = URLRequest(url: URL(string: strURL)!)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: dictParam, options: [])
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: { data, response, error -> Void in
print(response!)
do {
let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, AnyObject>
print(json)
completion(json)
} catch {
print("error")
}
})
task.resume()
}
API call:
let dictParams = ["ingr":["100 grams apple"]] as Dictionary<String, Any>
APICalling.shared.getData(strURL: baseURL, dictParam: dictParams) { (response) in
action()
}
}
When using the Rested app, I can upload as many ingredients as I want and will get the correctly formatted response, everything is dandy. However, when I try to implement the code in my app, it prints "error":conflict. Any ideas how I can properly implement the API call?
Found a fix to the issue. Added some headers to my request, everything works fine now.
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("*/*", forHTTPHeaderField: "Accept")
request.addValue("no-cache", forHTTPHeaderField: "Cache-Control")
request.addValue("api.edamam.com", forHTTPHeaderField: "Host")
request.addValue("gzip, deflate", forHTTPHeaderField: "Accept-Encoding")
request.addValue("keep-alive", forHTTPHeaderField: "Connection")

iOS swift Post request

So I want to create a post request with the following output:
"user"=>{"email"=>"test#test.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}
Instead I get:
{"user[password_confirmation]"=>"[FILTERED]", "user[email]"=>"test#test.com", "user[password]"=>"[FILTERED]", "user"=>{}}
This is the code I use to make this post request:
let request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
let session = NSURLSession.sharedSession()
let params = ["user[email]":username.text!, "user[password]":password.text!, "user[password_confirmation]":passwordRepeated.text!]
request.HTTPBody = try? NSJSONSerialization.dataWithJSONObject(params, options: [])
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: { data, response, error -> Void in
print(request.HTTPBody)
print(params)
print(error)
print(response)
print(data)
})
task.resume()
So how do I correctly create my params?
You are composing params incorrectly.
Do it like this,
let params = [
"user": [
"email": username.text!,
"password": password.text!,
"password_confirmation": passwordRepeated.text!
]
]

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

iOS : http Post using swift

I figured it out solution at the bottom
I am trying to make an HTTP post request to my server. Here's what I did
var request : NSMutableURLRequest = NSMutableURLRequest(URL : NSURL(string : "myURL")
let session : NSURLSession = NSURLSession.sharedSession()
request.allHTTPHeaderFields = (headers as [NSObject : AnyObject])
request.HTTPShouldHandleCookies = true
request.HTTPMethod = "POST"
var postData = "frontend=iOS"
request.HTTPBody = postData.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
NSHTTPCookieStorage.sharedHTTPCookieStorage().cookieAcceptPolicy = NSHTTPCookieAcceptPolicy.Always
println(request.allHTTPHeaderFields)
println(request.HTTPBody)
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
let json:JSON = JSON(data: data)
println(json)
onCompletion(json, error)
})
task.resume()
this is not setting the HTTPRequest.POST
I tried printing the request to the server on the server side. IT said post was empty
POST : [QueryDict : {}]
What am I missing here? Any help is appreciated
Solution :
I mistakenly set the content-value to application/json when in fact it
was not a json body. Removing it solved the problem
use https://github.com/Alamofire/Alamofire
easy networking :)
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.response { (request, response, data, error) in
println(request)
println(response)
println(error)
}
you can use all of the below.
public enum Method: String {
case OPTIONS = "OPTIONS"
case GET = "GET"
case HEAD = "HEAD"
case POST = "POST"
case PUT = "PUT"
case PATCH = "PATCH"
case DELETE = "DELETE"
case TRACE = "TRACE"
case CONNECT = "CONNECT"
}
Heres the method I used in my logging library: https://github.com/goktugyil/QorumLogs
var url = NSURL(string: urlstring)
var request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.HTTPBody = postData.dataUsingEncoding(NSUTF8StringEncoding)
var connection = NSURLConnection(request: request, delegate: nil, startImmediately: true)
See How to escape the HTTP params in Swift on the way to correctly encode key-value pairs into the data string.

Resources