Alamofire POST encoding issue - swift

I'm trying to login to a web service as follows:
func Login(completionHandler:#escaping (Bool) -> ()) {
let url = MyUrl
let parameters: Parameters = [
"Password":password,
"StayLoggedIn":NSNumber(value: true),
"UserName":username
]
var headers:HTTPHeaders = commonHeaders()
headers["Content-Type"] = "application/json;charset=UTF-8"
Alamofire.request(url, method:.post, parameters:parameters, headers:headers).responseJSON { response in
switch response.result {
case .success:
debugPrint(response)
case .failure(let error):
print(error)
}
}
}
Somehow, the server returns a 501 error.
I'm in the process of rewriting an Obj-c app in Swift, and replacing NSURLSessions with Alamofire into the bargain.
What I see in my working obj-c app, is that the headers sent to the server contain
Content-Type: application/json;charset=UTF-8
As you can see, I explicitly add this header to my request, but somehow, it is not sent to the server.
What I also see, is that my login credentials are not sent to the server.
So, I guess my question is: how do I tell Alamofire to use the correct encoding/content type?

try this encoding application/x-www-form-urlencoded instead of application/json;charset=UTF-8

Related

Alamofire request with authorization bearer token and additional headers Swift

My API includes authorization bearer token and three additional headers. My problem is I'm not sending the bearer token right (Postman return the correct data not my simulator). I see a lot of examples for using the request adapter but can I not use that? Thanks!
The auth is actually in the authorization tab not in the header.
**Updated:
Solved the problem by following the documentation.
HTTP Headers
Here is the Alamofire function with working codes:
func getBetsData(completion: ((Bool) -> ())? = nil) {
guard let token = defaults.string(forKey: "token") else {
return
}
let headers: HTTPHeaders = [
.authorization(bearerToken: token),
.init(name: "bet_type", value: type),
.init(name: "bet_status", value: status),
.init(name: "page", value: String(page))
]
AF.request("https://example.com", headers: headers).responseDecodable(of: Bets.self) { response in
switch response.result {
case .success:
if let data = response.data {
do {
let bets = try JSONDecoder().decode(Bets.self, from: data)
print("message: \(bets.message)")
self.setupTableData()
completion?(true)
} catch {
print("Error: \(error)")
completion?(false)
}
}
case.failure(let error):
print(error)
completion?(false)
}
}
}
You can add the headers directly:
let headers: HTTPHeaders = [.authorization(bearerToken: token)]
Additionally, if you're decoding a Decodable value from the response, you should not use responseJSON, as that decodes the Data using JSONSerialization and then you just parse it again. Instead, you should use responseDecodable.
AF.request(...).responseDecodable(of: Bets.self) { response in
// Use response.
}
That will be much more efficient and will capture errors for you automatically.
As mention by Dilan only token is not enought you will need to Bearer in the same Header parameter.
Here is one of the best method to handle Token Request and Retrier in all the request you send to server in the application
https://www.avanderlee.com/swift/authentication-alamofire-request-adapter/
By this you don't need to handle token manually in all the webservice.

How to call a post API which has parameters like get api in Alamofire Swift?

I have checked many stack overflow questions but unable to find answer for the following problem. How can I request a post api which has parameters like get api using Alamofire Swift?
Request:
http://dev.practice.com/api/v1/test/apply?id=51&social_id=2
Body:
"url": https://www.social.com/some_image_url
I have tried with the following way but it's not working:
let urlString = "http://dev.practice.com/api/v1/test/apply?id=51&social_id=2"
Alamofire.request(urlString, method: .post, parameters: ["url": "https://www.social.com/some_image_url"],encoding: JSONEncoding.httpBody, headers: header).responseJSON {
response in
switch response.result {
case .success:
print(response)
break
case .failure(let error):
print(error)
}
}
The answer is:
We have to request the get api like parameters as queryString and post body parameters as httpBody with the request.

Alamofire responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)

I had some working code that was getting results from a MySQL DB on a remote web server. It is no longer working and I keep getting the message responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength). Here is some code...
Alamofire.request(ADS_URL, method: .get).validate().responseJSON { response in
print("Request: \(String(describing: response.request))") // original url request
print("Response: \(String(describing: response.response))") // http url response
print("Result: \(response.result)") // response serialization result
switch response.result {
case .success(let value):
let json = JSON(value)
print ("JSON: \(json)")
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)") // original server data as UTF8 string
}
case .failure(let error):
print("Error while querying database: \(String(describing: error))")
return
}
}
I am also using SwiftyJSON. Here are the results of the code...
Request: Optional(http://doyouado.com/adscan/get_ads)
Response: Optional(<NSHTTPURLResponse: 0x17502f3a0> { URL: http://doyouado.com/adscan/get_ads } { status code: 200, headers {
Connection = "keep-alive";
"Content-Length" = 0;
"Content-Type" = "text/html; charset=UTF-8";
Date = "Mon, 18 Sep 2017 16:04:37 GMT";
Server = "nginx/1.12.1";
"Set-Cookie" = "ado_session=a%3A5%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%225019d90891c70c81df8ebc2fe754a68f%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A15%3A%22109.150.214.128%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A86%3A%22ADoBroadcaster%2F1.0+%28com.GaryFrank.ADoBroadcaster%3B+build%3A1%3B+iOS+10.3.3%29+Alamofire%2F4.5.0%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1505750677%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3B%7D3130ef6f5541e6f944da5a5a1292350bf203fa1b; expires=Mon, 18-Sep-2017 18:04:37 GMT; Max-Age=7200; path=/";
} })
Result: FAILURE
Error: responseSerializationFailed(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
I have tried using .response and .responseString, but I get no information returned. I am completley stumped. This was all working fine. Hopefully there is someone that can shed some light on this?
Just simply change .responseJSON to .responseData.
And after this parse data:
let jsonDecoder = JSONDecoder()
let parsedData = try jsonDecoder.decode(T.self, from: data)
and no error:
(Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)
What worked for me was changing the encoding from JSONEncoding.default to URLEncoding.default!
Updating from Alamofire 4 to 5 caused the issue in my case.
By default, it seems that Alamofire 5 returns the error Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength for empty response body with status code 200. So adding 200 to the list of emptyResponseCodes resolved the issue for me:
request.responseData(emptyResponseCodes: [200, 204, 205]) { ... } // the default is [204, 205]
What worked for me was changing from .responseData to .response
Commonly this error comes when your API is 'GET' type and you pass 'POST' type.
The same problem I faced and my solution is I replace .post to .get and then this error removed.
For AFNetworking 3.0 :-
go given path,
pods > Pods > AFNetworking > Serialization > AFURLResponseSerialization.m
then replace line no 228 (self.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript", nil];)
with
self.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/json", #"text/javascript", #"text/html", nil];
Because of your response in form of text/html but that is not mentioned in AFNetworking then we add it manually.
Note:- I debugging this problem for Alamofire.
When server sends back no response, Alamofire shows this message in the .failure block if you are printing the error message. Technically it is not an error. Alamofire didn't show this message in its earlier versions, but since one of the recent updates it started showing it.
As I said it is not really an error, but to me its a bug in Alamorfire. And it is very annoying and misleading to keep seeing this in your log when there is no error on your client or server side.
Here is how I silent it:
if (response.data?.count)! > 0 {print(error)}
And I do it when there is no response from the server, which is the expected behaviour since server is not supposed to send response in some cases.
Alamofire.request(MY_URL, method: .get, parameters: ["blabla": blablabla])
.validate(statusCode: 200..<300)
.responseJSON {
response in
switch response.result {
case .success(let value):
self.processResponse(value)
case .failure(let error):
if (response.data?.count)! > 0 {print(error)}
}
}
So the error message doesn't shows when nothing is returned from the server. In my opinion this should be the default behaviour.
Though the question is quite old, I wanted to provide to others what I recently discovered.
Since the error message is very generic and it doesn't help much, check that the url format you are using is correct. I've gotten this only to discover that the url format was incorrect. Once fixed things started working fine.

Swift Alamofire POST request becomes GET

That's the code I'm using to make POST request to my Flask server in localhost:
func data_request() {
let url:NSURL = NSURL(string: "http://192.168.1.192:9880/api/register")!
Alamofire.request(.POST, url, parameters: ["login":"login", "password" : "12345"]).responseJSON { response in
switch response.result {
case .Success:
NSLog("Validation Successful")
case .Failure(let error):
NSLog("\(error), \(String(data: response.data!, encoding: NSUTF8StringEncoding))")
return
}
if (response.result.value as? [String: AnyObject]) != nil{
print(response.result.value)
}
}
}
But it sends GET request! Both server and local proxy tell it was GET request - that's what Burp has intercepted:
GET /api/register/ HTTP/1.1
Host: 192.168.1.192:9880
Accept: */*
User-Agent: Project Manager/Roman-Nikitin.Project-Manager (1; OS X 10.11.3)
Accept-Language: en;q=1.0, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5
Accept-Encoding: gzip;q=1.0, compress;q=0.5
Connection: close
I had the same problem, you just have to put / at the end of URL. Problem is in Alamofire, I think. It works weird with normal server redirections from www.domain.com/something to www.domain.com/something/
For anyone getting here because they have the same problem (like me): In my case, I already had a / at the end and I had to remove it.
Based on this answer, it seems to be the server redirecting the original POST request to a GET request. So either figure out what your server requires (trailing slash or no), or set up the server like in the linked answer.

Alamofire HTTP sent twice SWIFT

every one,
I'm having an issue with Alamofire 3.0, when I post data, it seems the data is being sent twice.
I looked up on the web, found that a bug about special caratères was fixed, but I still get the error.
Anyone has an idea. I'm using a parameter in the header called X-Authorization.
Here is an extract of the code i'm using:
static func postData (url: String,token: String,params :Dictionary<String,AnyObject>){
print("POSTINGGGGGG")
Alamofire.request(.POST, url, parameters: params,headers: ["X-Authorization": token])
.responseJSON { response in
switch response.result {
case .Success(let data): break
//let resultJSON = JSON(data).dictionaryValue
// print(data)
case .Failure(let error):
print(error)
}
}
}
Thank you in advance,
Morgan