Converting CURL command for Locu to Swift - swift

The Locu API provides this example using CURL to perform a location sensitive query:
curl -X POST https://api.locu.com/v2/venue/search -d '{
"api_key" : "f165c0e560d0700288c2f70cf6b26e0c2de0348f",
"fields" : [ "name", "location", "contact" ],
"venue_queries" : [
{
"location" : {
"geo" : {
"$in_lat_lng_radius" : [-37.7750, 122.4183, 5000]
}
}
}]
}'
This is my attempt in Swift:
let LOCU_API_KEY = "<API_KEY>"
let centerLatitude = mapView.region.center.latitude
let centerLongitude = mapView.region.center.longitude
let arr = [centerLatitude,centerLongitude,5000]
let url = NSURL(string: "https://api.locu.com/v2/venue/search")
var request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
var params = ["api_key":LOCU_API_KEY,"fields":["name","location","contact"], "venue_queries":[["location":["geo":["$in_lat_lng_radius":arr]]]]] as [String:AnyObject!]
var err: NSError?
NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: { (response:NSURLResponse!, data:NSData!, error:NSError!) -> Void in
if error == nil {
var err:NSError?
let httpResponse = response as NSHTTPURLResponse!
println(response.description)
if httpResponse.statusCode == 200 {
if var json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error:&err) as? NSDictionary {
println(json)
}
}
}
})
I only get an HTTP 400 - Bad request for this and various simplifications, like just providing the api_key. Version 1_0 of the Locu works fine, although it doesn't have the features I need.

afRequestOperationManager.GET is performing a GET request rather than a POST request.
Furthermore, the request data must be in JSON, whereas you are using URL parameters.

As others have said you need to use .POST or in someway do a POST request not a GET.
Also, it looks like this line:
let urlString = "https://api.locu.com/v2/venue/"
Should be:
let urlString = "https://api.locu.com/v2/venue/search"
Right? Notice the "search" at the end. That is why you are getting 400 I assume (404 I guess?!).
Let us know if it worked.

The '-X POST part of the curl command means you need to do an HTTP POST, not an HTTP GET.
Try using afRequestOperationManager.POST instead.

Related

Alamofire multiple parameters (Query and Form) Swift 4

I'm having a problem sending a POST request with Alamofire.
I need to send the usser and password fields as application/x-www-form-urlencode and also some query data in the url.
I am creating a URLRequest to handle the process, but I'm getting always a 400 response from the server, so I guess the problem must be in the way I create the request.
This is the example in Postman:
I need to send a param in the url and two more in as application/x-www-form-urlencode
Postman 1 - Parameters
Postman 2 - ContentType
I need to do this (that i have in Android)
#FormUrlEncoded
#POST(Constants.AUTH_LDAP)
Call<ResponseBody> authLdap(
#Query(value = Constants.PARAM_REQ, encoded = true) String req,
#Field(Constants.PARAM_LOGIN) String login,
#Field(Constants.PARAM_PASSWORD) String password
);
And this is what I have in swift
let queryParamters = [Constants.Params.PARAM_REQ:req]
let headers = ["Content-Type": "application/x-www-form-urlencoded"]
let fieldParameters = [
Constants.Params.PARAM_LOGIN : user,
Constants.Params.PARAM_PASSWORD : pass]
let url = URL(string: Constants.EndPoints.AUTH_LDAP)
let request = URLRequest(url: url!)
let encoding = try URLEncoding.default.encode(request, with: queryParamters as Parameters)
let encodingpa = try URLEncoding.httpBody.encode(request, with: fieldParameters as Parameters)
var urlRequest = encodingpa
urlRequest.url = encoding.url
urlRequest.allHTTPHeaderFields = headers
Alamofire.request(urlRequest).responseData(completionHandler: { response in
switch response.result {
case .success:
print("sucess")
print(response.response)
case .failure(let error):
print(error)
}
})
Thanks for your help.
Try to create url from queryParameters using URLComponents like
var urlComponents = URLComponents(string: Constants.EndPoints.AUTH_LDAP)!
urlComponents.queryItems = [
URLQueryItem(name: Constants.Params.PARAM_REQ, value: req)
]
let headers = ["Content-Type": "application/x-www-form-urlencoded"]
var request = URLRequest(url: urlComponents.url!)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: fieldParameters)
request.allHTTPHeaderFields = headers
Alamofire.request(request).responseJSON { response in
}

HTTP POST request with String and NSDate Swift

i'm have this parameters on payload to send a POST request to backend
'{"token":"xxxx", "extra_information": {"expires_in": xxxx, "refresh_token": "xxx", "user_id": "user_uuid", "token_type": "Bearer"}}'
Parameters with "xxxx" will be come by integration. I'm try create a function to send this
func sendAuth() {
if let url = NSURL(string: "https://xxxxxxxxxxxx"){
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let token = AccessToken?()
let params = ["token" : (token?.tokenString)!, "refresh_token" : (token?.refreshToken)!,"expires_in" : (token?.expirationDate)!, "user_id" : "uber_uuid" , "token_type" : "Bearer"] as Dictionary <String,String>
let httpData = NSKeyedArchiver.archivedDataWithRootObject(params)
request.HTTPBody = httpData
let session = ServicesUtils.BaseSessionManager()
session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
print("\(strData)")
}).resume()
After write this xCode show me a error "Cannot convert Value of Type NSDate to expected dictionary value Type String" due to parameter expires_in receive a NSDate.
Edit 1 - After change Dictionay receive strData occured error "Cannot convert value of type 'NSURLResponse to expected argument type 'NSData'"
Its because you are casting params as Dictionary <String,String> thats why it will not accept NSDate as value in your dictionary.
You need to change it like Dictionary <String,AnyObject> and it will work.

Swift REST Request PUT Optional(502 Bad Gateway: Registered endpoint failed to handle the request.)

I'm trying to do a PUT request using Swift. In a REST client, when I try to do a REST request the following way:
In Body- x-www-form-urlencoded, I add vote=1 and with id being taken in the param for example: /user/:id, it works!
I try to do the same in Swift code, it does not work and I get responseString = Optional(502 Bad Gateway: Registered endpoint failed to handle the request.
Here is my code:
var baseURL = "http://<domain>/user"
let putURL = baseURL + "/\(id)"
print(putURL)
let request = NSMutableURLRequest(URL: NSURL(string: putURL)!)
request.HTTPMethod = "PUT"
let putString = "vote=1"
request.HTTPBody = putString.dataUsingEncoding(NSUTF8StringEncoding)
request.timeoutInterval = 1500
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
guard error == nil && data != nil else {
print("error=\(error)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
task.resume()
You forgot to set the content type, e.g.
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
Without that, the server won't know what to do with the blob of random data that you just sent it.
I'm not saying that this is necessarily the only problem, but it is definitely a problem, and one big enough to cause the error you're seeing.

Alamofire Custom Parameter Encoding

I'm using Alamofire and want to encode my parameters with content type "text/html; charset=utf-8". I followed the documentation https://github.com/Alamofire/Alamofire for custom parameter encoding and created
let custom: (URLRequestConvertible, parameters: [String: AnyObject]?) -> (NSURLRequest, NSError?) = {
(URLRequest, parameters) in
let mutableURLRequest = URLRequest.URLRequest.mutableCopy() as! NSMutableURLRequest
mutableURLRequest.setValue("text/html; charset=utf-8", forHTTPHeaderField: "Content-Type")
mutableURLRequest.body = // don't know if I need to set this
return (mutableURLRequest, nil)
}
func postData(){
Alamofire.request(.POST, baseUrl, parameters: parameters, encoding: .Custom(custom))
.responseString{ (request, response, data, error) in
println("blah")
}
}
I have a problem when I try to use custom in my Alamofire request and get the error "Cannot make responseString with argument list of type ( _, _, _, _)-> _ )" However, this isn't a problem if the encoding is changed to a preset like .URL so the issue seems to be in my implementation of custom?
If it makes a difference my parameters are set here:
var parameters = [String: AnyObject]()
func setParams(){
parameters = [
"CONTRACT ID" : chosenContract!.iD.toInt()!,
"FEE AMOUNT" : 0,
"TRANSACT DATE" : today
]
}
You have a couple questions in here. Let's break them down 1x1.
Compiler Issue
Your compiler issue is due to the fact that your return tuple is the wrong type. In Alamofire 1.3.0, we changed the return type to be an NSMutableURLRequest which ends up making things much easier overall. That should fix your compiler issue.
Setting the HTTPBody
Now you have a couple options here.
Option 1 - Encode Data as JSON
let options = NSJSONWritingOptions()
let data = try NSJSONSerialization.dataWithJSONObject(parameters!, options: options)
mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
mutableURLRequest.HTTPBody = data
From what you posted I'm assuming you actually want .URL encoding for the parameters.
Option 2 - Use the .URL Case
let parameters: [String: AnyObject] = [:] // fill in
let encodableURLRequest = NSURLRequest(URL: URL)
let encodedURLRequest = ParameterEncoding.URL.encode(encodableURLRequest, parameters).0
let mutableURLRequest = NSMutableURLRequest(URL: encodedURLRequest.URLString)
mutableURLRequest.HTTPMethod = "POST"
mutableURLRequest.setValue("text/html; charset=utf-8", forHTTPHeaderField: "Content-Type")
Alamofire.request(mutableURLRequest)
.response { request, response, data, error in
print(request)
print(response)
print(error)
}
Hopefully that helps get you going. Best of luck!

Swift HTTP Post: Why are these params not being recognized?

I am making a simple HTTP Post call to a webserver in Swift, and trying to pass several parameters via a Dictionary, but the server doesn't seem to receive them, what am I missing here? I can do this in PHP, Perl, etc, but haven't quite figured out passing POST params in Swift. Thanks.
var ret: NSData
var responseStr: NSString
var urlString = server + page
var url:NSURL = NSURL(string: urlString)! // Creating URL
var request = NSMutableURLRequest(URL: url) // Creating Http Request
request.HTTPMethod = "POST"
// these params don't seem to be recognized
let params = [
"projectid": "1234", "userid": "somename", "password": "pw"
] as Dictionary<String, String>
var err: NSError?
let requestBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.HTTPBody = requestBody
var response: AutoreleasingUnsafeMutablePointer<NSURLResponse?> = nil
var error: NSErrorPointer? = nil
A Content-Type header with value application/json is usually needed for server-side apps to recognize JSON-formatted request body. So add this before you make the request:
request.addValue("application/json", forHTTPHeaderField:"Content-Type")
Another solution is use a library like Just. Your request would be:
Just.post(urlString, json: ["projectid": "1234", "userid": "somename", "password": "pw"])