Post request error with parameter encode when use moya and alamofire - ios

I use the moya make the post request,but when I send the post , the server give me an error, it can't decoding the body parameters.I use URLEncoding.default to encode the parameters like this
public var parameterEncoding: ParameterEncoding {
return URLEncoding.default
}
It will set the content-type application/x-www-form-urlencoded, and the server accept content type is same too
if parameters is a dictionary like this {"a":"b"} ,that is working well, but if dictionary contained array or another dictionary ,the server can't get the parameters from request body.
EX:
{
"a":"xxx",
"b":[
"xxxxx",
"xxxxx"
]
}
alamofire will encode this like
"a"="xxx"&b[]=xxxx&b[]=xxx
but the server expect a=xxx&b[0]=xxx&b[1]=xxxx
how to solve this problem ?

You can build the parameter string manually, and then link the parameter string to Url string. Finally, just make request with url by Alamofire, without any parameters(they are in url already).
The way to build parameter string:
let dict = ["a":"xxx","b":["xxx","xxxxxxx"]] as [String : Any]
var paramString = ""
for key in dict.keys {
let value = dict[key]
if let stringValue = value as? String {
paramString += "&\(key)=\(stringValue)"
}
else if let arr = value as? Array<String> {
for i in 0 ... arr.count - 1 {
paramString += "&\(key)[\(i)]=\(arr[i])"
}
}
else{
//other type?
}
}
if paramString.characters.count > 0 {
paramString = paramString.substring(from: paramString.index(paramString.startIndex, offsetBy: 1))
}
print(paramString)
//output is: b[0]=xxx&b[1]=xxxxxxx&a=xxx

Related

Don't want to sort parameter in sort sequence alamofire

Here is my request of my api
http://xxxxxxxxxxxxxx/Service/GetEntry.aspx?FromDate=01/08/2018&RID=1&ToDate=25/10/2018&TokenID=1e731b96-4261-453b-848c-5b1a0d44f808
But my original request is like
http://xxxxxxxxxxxxx/Service1/GetEntry.aspx?TokenID=5edc678f-82ee-4cf8-956e-5f1d3798dfec&RID=1&FromDate=01%2F08%2F2018&ToDate=25%2F10%2F2018
Here are my request param and api call
var param = [String:Any]()
param["TokenID"] = tokenId
param["RID"] = Rid
param["FromDate"] = DateUtilities.convertStringfromDate(date: DateUtilities.getDateofMonthStartOfLast2Month())
param["ToDate"] = DateUtilities.convertStringfromDate(date: Date())
print(param)
// Network request
Alamofire.request(finalURL, method: .post, parameters: param, encoding: URLEncoding.queryString, headers: headers).responseJSON { (response: DataResponse<Any>) in
// check result is success
guard response.result.isSuccess else {
failure((response.result.error?.localizedDescription)!,"100")
return
}
if let arrResponse = response.result.value as? [[String: Any]]{
// get status code
if arrResponse[0]["Status"] as? String ?? "" == "Error"{
let statusCode = arrResponse[0][Constants.ResponseKey.code] as? String ?? "0"
if statusCode == "8"{
//Call logout api
ApplicationData.sharedInstance.logoutUser()
return
}
// get status message
let message = arrResponse[0][Constants.ResponseKey.message] as? String ?? ""
failure(message,statusCode)
return
}
success(arrResponse, "")
return
}
}
But due to sequence mismatch I do not get as per desired response, I am getting error in api response.Here I think it is problem of alamofire which taking parameters in sorting into querystring. How can I avoid sorting in request?
Please help me with it.
Apparently this is a closed issue on Alamofire already Follow this link.
Unfortunately Swift's dictionaries aren't order preserving, so there's
no way to currently accomplish this.
Alamofire currently encodes URL parameters in alphabetical order, but
there's no way to preserve an arbitrary ordering in the dictionary. So
unless the order is want is a sort of some kind, or the arbitrary
ordering of the dictionary.

Add elements from SwiftyJSON to URL array in Swift

I'm retrieving a list of URL images using Alamofire. The response is in JSON And I have used SwiftyJSON to parse and print each element. I want the URLs to be added into a URL array. Below is the code I have used
var newArray = [URL(string: "http://www.tummyvision.com/users/uploads/gijovarghese141#gmail.com/photos/4.jpg")]
Alamofire.request("http://www.tummyvision.com/users/login/get-images.php", parameters: parameters).responseData { response in
let json = JSON(data: response.result.value!)
for i in 0..<json.count
{
print(json[i]) // prints the correct url
self.urlArray.append(json[i])
}
}
But it is giving me the following error:
Try to use arrayValue property of JSON to access array also you need to convert String Url to URL object before adding it into Array of URL.
if let urls = json.arrayValue {
for url in urls {
self.urlArray.append(URL(string:url))
}
}

IOS Swift Alamofire JSON Request

I am trying to make a JSON Request with Alamofire but the response is in Greek and Swift returns:
Response
{
id = 4;
name = "\U0395\U03bb\U03b1\U03b9\U03cc\U03bb\U03b1\U03b4\U03bf"
url = "http://www.gaiaskarpos.com/app/images/categories/olive.png";
}
The problem is at name field.
//Swift Alamofire Request
Alamofire.request(.GET, "http://gaiaskarpos.com/applegetCategores.php",
encoding:.JSON).validate().responseJSON{(response)->
Void in print("Response Json : \(response.result.value)")
I had a same issue in Arabic/Persian chars and It's my solution:
json variable :
{
message = "\U062f\U0633\U062a\U06af\U0627\U0647 \U0645\U0639\U062a\U0628\U0631 \U0646\U06cc\U0633\U062a";
status = 0;
}
So I casted json to [String: AnyObject] :
var test = json as? [String : AnyObject]
print(test)
It's fixed. You should give it a try.
Why is your encoding .JSON? You send .GET-request and you don't need to specify the type of encoding in your request.
Alamofire documentation say:
Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
So use it. Links -> http://cocoadocs.org/docsets/Alamofire/1.1.3/ and https://github.com/Alamofire/Alamofire
You must specify the type of encoding when you pass parameters in the body of your request. It is for .POST and .PUT requests.
Try to print 'name' to Debug area. Maybe you'll get name in normal encoding... Xcode has the disadvantage: it shows not-UTF8 data in response like '\U0395\U03bb ... ... ... \U03b1\U03b9\' when there is some level of nested data in response.
Try to use NSUTF8StringEncoding with alamofire response
encoding: NSUTF8StringEncoding
Try to serialize the JSON with below code this might help you
let dict = NSJSONSerialization.JSONObjectWithData(jsonString.dataUsingEncoding(NSUTF8StringEncoding)!,
options: nil, error: nil) as [String : String]

Swift URL query string get parameters

I'm using the OAuthSwift library to authenticate users of my app, but something doesn't seem to be working as it throws an error. After some debugging it seems to be going wrong on this line: parameters = url.query!.parametersFromQueryString()
It does have the url query string (set to url.query) but it somehow fails parsing the parametersFromQueryString(). Does someone else have this problem (with this library) and how did you solve it?
The "parametersFromQueryString" function can be found here: https://github.com/dongri/OAuthSwift/blob/1babc0f465144411c0dd9721271f239685ce83a9/OAuthSwift/String%2BOAuthSwift.swift
Create an extension of URL class and paste this code:
import Foundation
extension URL {
public var parametersFromQueryString : [String: String]? {
guard let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems else { return nil }
return queryItems.reduce(into: [String: String]()) { (result, item) in
result[item.name] = item.value
}
}}
Now you can get the value of this calculated attribute from URL object by simply using:
url.parametersFromQueryString
Have you checked that url.query returns anything? and that it is url decoded before/after calling url.query?
try looking at the answers here:
URL decode in objective-c
If the method is looking for characters such as '?' or '=' and the URL is still encoded, it might not find them
Here is the same code as it should look like in swift:
let URLString = "http://sound17.mp3pk.com/indian/barfi/%5BSongs.PK%5D%20Barfi%20-%2001%20-%20Barfi!.mp3"
let URL = NSURL(string:url)
let filename = URL.path.lastPathComponent.stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
//=> [Songs.PK] Barfi - 01 - Barfi!.mp3

How can I access the "Content-Type" header of an NSHTTPURLResponse?

Here's my naive first pass code:
var httpUrlResponse: NSHTTPURLResponse? // = (...get from server...)
let contentType = httpUrlResponse?.allHeaderFields["Content-Type"]
I've tried various derivations of this code, but I keep getting compiler warnings/errors related to the basic impedance mismatch between the NSDictionary type of the allHeaderFields property and my desire to just get a String or optional String.
Just not sure how to coerce the types.
You can do something like the following in Swift 3:
if
let httpResponse = response as? HTTPURLResponse,
let contentType = httpResponse.value(forHTTPHeaderField: "Content-Type")
{
// use contentType here
}
task.resume()
Obviously, here I'm going from the URLResponse (the response variable) to the HTTPURLResponse. And rather than fetching allHeaderFields, I’m using value(forHTTPHeaderField:) which is typed and uses case-insensitive keys.
Hopefully this illustrates the idea.
For Swift 2, see previous revision of this answer.
This works with Xcode 6.1:
let contentType = httpUrlResponse?.allHeaderFields["Content-Type"] as String?
Multiple casts no longer required.
And in Xcode 6.3 with Swift 1.2, this works:
let contentType = httpUrlResponse?.allHeaderFields["Content-Type"] as? String
I use an extension to URLResponse to simplify this one (Swift 3):
extension URLResponse {
func getHeaderField(key: String) -> String? {
if let httpResponse = self as? HTTPURLResponse {
if let field = httpResponse.allHeaderFields[key] as? String {
return field
}
}
return nil
}
}
Could you just use the MIMEType property?
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSURLResponse_Class/#//apple_ref/occ/instp/NSURLResponse/MIMEType
Actually it should be as easy as this
NSString* contentType = [[(NSHTTPURLResponse*)theResponse allHeaderFields] valueForKey:#"content-type"];
or
NSString* contentType = [[(NSHTTPURLResponse*)theResponse allHeaderFields][#"content-type"]];
But the problem is that the response might return the name of the key as an upper case one or a lower case one, while NSDictionary is really case sensitive about keys, so you should do your own case insensitive search for the key
NSDictionary* allFields = [[(NSHTTPURLResponse*)theResponse allHeaderFields];
NSString* contentType;
for (NSString* key in allFields.allKeys) {
if ([key compare:#"content-type" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
// This is it
contentType = allFields[key];
break;
}
}

Resources