How to send a HTTP POST like this in Swift? - ios

{
"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)
}
}

Related

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

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

'API Key Missing' when making Mailchimp API call from Swift 5 iOS App

I am trying to add a subscriber to my mailing list from my Swift 5 iOS app. I am seeing the following error when trying to do this:
{
detail = "Your request did not include an API key.";
instance = "3f4cb654-c674-4a97-adb8-b4eb6d86053a";
status = 401;
title = "API Key Missing";
type = "http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/";
}
Of course this indicates that I am missing my API Key, however I am specifying it in the Authorization header (see below code). I have tried a mix of the answer here and the guide here but I'm not having much luck so far. Here's my current code for setting up the request:
let mailchimpAPIURL = "https://us3.api.mailchimp.com/3.0"
let requestURL = NSURL(string: mailchimpAPIURL)!
let apiCredentials = "anystring:<API_KEY>"
let loginData = apiCredentials.data(using: String.Encoding.utf8)!.base64EncodedString()
let params = [
"list_id": "<LIST_ID>",
"email_address": email,
"status": "subscribed",
"merge_vars": [
"FNAME": firstName,
"LNAME": lastName
]
] as [String: Any]
let request = NSMutableURLRequest(url: requestURL as URL)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Basic \(loginData)", forHTTPHeaderField: "Authorization")
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
} catch {
return
}
You need to send api key in the authorization header like this:
let params: [String: AnyObject] = ["email_address": email, "status": "subscribed"]
guard let url = "https://us10.api.mailchimp.com/3.0/lists/<listID>/members/".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) else { return }
let credentialData = "user:<apikey>".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials = credentialData.base64EncodedStringWithOptions([])
let headers = ["Authorization": "Basic \(base64Credentials)"]
Alamofire.request(.POST, url, headers: headers, parameters: params, encoding: .URL)
.responseJSON { response in
if response.result.isFailure {
}
else if let responseJSON = response.result.value as? [String: AnyObject] {
}
}
Okay, I got it. #Sam's answer helped me realise that the URL I was using was wrong, and I needed to add the ListID into that URL. I also changed setValue to addValue, and changed NSMutableURLRequest to URLRequest. I also added request.httpMethod = "POST" Here is my updated, working code:
let subscribeUserURL = "https://us3.api.mailchimp.com/3.0/lists/<LISTID>/members/"
let requestURL = NSURL(string: subscribeUserURL)!
let apiCredentials = "anystring:<APIKEY>"
let loginData = apiCredentials.data(using: String.Encoding.utf8)!.base64EncodedString()
let params = [
"email_address": email,
"status": "subscribed",
"merge_fields": [
"FNAME": firstName,
"LNAME": lastName
]
] as [String: Any]
var request = URLRequest(url: requestURL as URL)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("Basic \(loginData)", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: [])
} catch {
return
}

How to send a request with alamofire with xml Body

I installed Alamofire in my project and now here is what I have done.
I installed postman and I put my url and inside body a xml object and I got my result.
Here is a picture of what I exactly have done with postman
How can I now use Alamofire or SWXMLHash to send it as I send it with postman
Thanks in advance!
EDIT
I tried this from another question:
Alamofire.request(.POST, "https://something.com" , parameters: Dictionary(), encoding: .Custom({
(convertible, params) in
let mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest
let data = (self.testString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
mutableRequest.HTTPBody = data
return (mutableRequest, nil)
}))
.responseJSON { response in
print(response.response)
print(response.result)
}
}
But it didn't send anything
This is the log:
Optional( { URL:
https://something.com } { status code: 200, headers {
Connection = "keep-alive";
"Content-Length" = 349;
"Content-Type" = "application/xml";
Date = "Wed, 02 Nov 2016 21:13:32 GMT";
Server = nginx;
"Strict-Transport-Security" = "max-age=31536000; includeSubDomains"; } })
FAILURE
EDIT
NEVER FORGET TO PASS parameters if you don't have simple add this , parameters: Dictionary()
Using Swift 3 and Alamofire 4
let stringParams : String = "<msg id=\"123123\" reqTime=\"123123\">" +
"<params class=\"API\">" +
"<param name=\"param1\">123213</param>" +
"<param name=\"param2\">1232131</param>" +
"</params>" +
"</msg>"
let url = URL(string:"<#URL#>")
var xmlRequest = URLRequest(url: url!)
xmlRequest.httpBody = stringParams.data(using: String.Encoding.utf8, allowLossyConversion: true)
xmlRequest.httpMethod = "POST"
xmlRequest.addValue("application/xml", forHTTPHeaderField: "Content-Type")
Alamofire.request(xmlRequest)
.responseData { (response) in
let stringResponse: String = String(data: response.data!, encoding: String.Encoding.utf8) as String!
debugPrint(stringResponse)
}
With Swift 3 and Alamofire 4 you would create a custom ParameterEncoding. As with any other XML encoded body, SOAP messages can use this parameter encoding as in the following example. Other XML body encodings can be created similarly (check the line where it says urlRequest.httpBody = ...):
struct SOAPEncoding: ParameterEncoding {
let service: String
let action: String
func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
var urlRequest = try urlRequest.asURLRequest()
guard let parameters = parameters else { return urlRequest }
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("text/xml", forHTTPHeaderField: "Content-Type")
}
if urlRequest.value(forHTTPHeaderField: "SOAPACTION") == nil {
urlRequest.setValue("\(service)#\(action)", forHTTPHeaderField: "SOAPACTION")
}
let soapArguments = parameters.map({key, value in "<\(key)>\(value)</\(key)>"}).joined(separator: "")
let soapMessage =
"<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/' s:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>" +
"<s:Body>" +
"<u:\(action) xmlns:u='\(service)'>" +
soapArguments +
"</u:\(action)>" +
"</s:Body>" +
"</s:Envelope>"
urlRequest.httpBody = soapMessage.data(using: String.Encoding.utf8)
return urlRequest
}
}
And then use it like that:
Alamofire.request(url, method: .post, parameters: ["parameter" : "value"], encoding: SOAPEncoding(service: "service", action: "action"))
Assuming you that you're missing valid HTTP headers in your request, the updated request could look like:
Alamofire.request(.POST, "https://something.com", parameters: Dictionary() , encoding: .Custom({
(convertible, params) in
let mutableRequest = convertible.URLRequest.copy() as! NSMutableURLRequest
let data = (self.testString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
mutableRequest.HTTPBody = data
mutableRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
return (mutableRequest, nil)
}))
.responseJSON { response in
print(response.response)
print(response.result)
}
}
So, basically you should add one line
mutableRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
Update:
Try same, but use responseData or responseString instead of responseJSON because it is possible that your response is not JSON

Alamofire put with array of ObjectMapper

I have array of ObjectMapper:
var arr = [Model]
now how can i use Alamofire to send this array to server with .PUT or .POST method?
Alamofire.request(.PUT, Config().apiGroup, parameters: arr, encoding: .JSON)
it says that parameters type is [String : AnyObject]?.
I tried with this too:
var params = Array<AnyObject>()
for entry in arr {
params.append(Mapper().toJSON(entry))
}
and then to pass params to parameters, but still getting error.
Any solution?
You can do this to convert:
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = HTTPMethod.post.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let pjson = attendences.toJSONString(prettyPrint: false)
let data = (pjson?.data(using: .utf8))! as Data
request.httpBody = data
Alamofire.request(request).responseJSON { (response) in
print(response)
}

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