How to prevent alamofire to put "&" sign to front of parameter - ios

I'm a beginner in Swift. I'm trying to create an application using PUBG api. I add my headers using Alamofire. I have a text field on my storyboard , I enter my nickname there and get the data from pubg api. My problem is Alamofire adds "&" sign to front of parameters so this crashes the url. How can I prevent Alamofire to put "&" sign to parameter?
let playerURL = "https://api.pubg.com/shards/pc-eu/players?filter[playerNames]"
func findPlayer(playerName:String){
let httpParameters : Parameters = ["":playerName]
Alamofire.request(playerURL,method:.get,parameters:httpParameters,encoding:URLEncoding.default,headers:httpHeaders).responseJSON{response in switch response.result{
case .success(let value):
let response = JSON(value)
print(response["data"])
case .failure(_):
return
}
}
}
URL should be like this:
https://api.pubg.com/shards/pc-eu/players?filter%5BplayerNames%5D=PlayerName
Instead it becomes this:
https://api.pubg.com/shards/pc-eu/players?filter%5BplayerNames%5D&=PlayerName

If you're using Alamofire to encode the parameters, then you need to let it encode the parameters:
let playerURL = "https://api.pubg.com/shards/pc-eu/players"
....
let httpParameters : Parameters = ["filter[playerNames]": playerName]
...
My entire test case is as follows:
Create a blank one-view project
In AppDelegate add:
let playerURL = "https://api.pubg.com/shards/pc-eu/players"
func findPlayer(playerName:String){
let httpParameters : Parameters = ["filter[playerNames]": playerName]
let request = Alamofire.request(playerURL,
method:.get,
parameters:httpParameters)
print(request)
}
In application(_:didFinishLaunchingWithOptions:) add:
findPlayer(playerName: "PLAYERNAME")
Run
Output:
GET https://api.pubg.com/shards/pc-eu/players?filter%5BplayerNames%5D=PLAYERNAME

Related

-1103 Error Domain=NSURLErrorDomain Code=-1103 "resource exceeds maximum size" iOS 13

We are facing the following networking error when the response is somehow large(14kb) on iOS 13.
[-1103] Error Domain=NSURLErrorDomain Code=-1103 "resource exceeds maximum size"
As we are using Alamofire, this problem is treated as error result which breaks our treatments of the results.
The strange thing is that if we use NSURLSession directly, though this error is still seen from logging, we don't actually receive it in the callback of
session.dataTask(with: request) { value, response, error in ... }
So the result can treated correctly.
This problem is never seen before. Anyone has got some idea on that ?
With the help of the Slack community, we find the answer is that
on iOS13, it is not allowed to add a body in GET request. To make it work again, we can either switch to a POST/PUT request or add body value via url parameters of the GET request.
Pass query parameters in GET request like the following:
let parameters: Parameters = [
"param": value
]
Alamofire.request(urlString, method: .get, parameters: parameters, encoding: URLEncoding.queryString)
I have face same issue and find out the solution.
You can't pass parameter in body while using GET.
Either use POST method if API support or pass it in URL like below.
AnyURL?Parameter=Value&Parameter=Value
Finally found the answer. For GET services I was trying to add an httpBody. Something like this:
do {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
errorCompletion(error)
return
}
The solution was just to add an if to avoid that chunk of code if httpMethod is a GET. Seems like an iOS 13 new behavior and the error message given by Swift definitely not helps at all
Alamofire: You should try this!
Alamofire.request(urlString, method: .get, parameters: parameters, encoding: URLEncoding.queryString)
Just avoid the httpBody for the GET API request.
if requestType != .get{
request.httpBody = data
}
#OR
For GET request append parameter into URL instead of the HTTP body
Use the below extension to create a query parameter from the dictionary.
extension NSObject {
func buildQueryString(fromDictionary parameters: [String:String]) -> String {
var urlVars = [String]()
for (var k, var v) in parameters {
let characters = (CharacterSet.urlQueryAllowed as NSCharacterSet).mutableCopy() as! NSMutableCharacterSet
characters.removeCharacters(in: "&")
v = v.addingPercentEncoding(withAllowedCharacters: characters as CharacterSet)!
k = k.addingPercentEncoding(withAllowedCharacters: characters as CharacterSet)!
urlVars += [k + "=" + "\(v)"]
}
return (!urlVars.isEmpty ? "?" : "") + urlVars.joined(separator: "&")
}
}
I used default url encoding instead of default json encoding and it's worked for me.
Alamofire.request(url, method: .get, parameters: param, encoding: URLEncoding.default)
OR
If you using URLRequestConvertible
enum NetworkRouter: URLRequestConvertible {
case someCase(lang:String)
var method: HTTPMethod {
return .get
}
var parameters: Parameters? {
switch self {
case .someCase(let param):
return ["lang": param.lang]
default:
return nil
}
}
var url: URL {
switch self {
case .someCase(let param):
return URL(string: Constants.baseURL + Constants.endPoint)!
default:
return URL(string: Constants.baseURL)!
}
}
var encoding: ParameterEncoding {
return URLEncoding.default
}
func asURLRequest() throws -> URLRequest {
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = method.rawValue
return try encoding.encode(urlRequest, with: parameters)
}
}
I got that issue because i pass empty parameters in Alamofire when send get request. So, instead of sending empty parameters i simply replace it for nil.
My fix is I only set .parameters to nil, then everything works fine. Because in Swift it still initialize the value of .parameters.
self.request.parameters = nil
Here you might have missing the method of the URL request that you are passing to data task. You have to add POST/PUT/DELETE to the URL request method parameter like below.
var request: URLRequest = URLRequest(url: SOME_VALID_URL)
request.body = SOME_VALID_DATA_IN_BYTES
request.method = "post" --> You are missing this.
I only see this issue when I build with Xcode 11. If I revert back to Xcode 10.3 I do not have the same issue anymore. While not a forever fix, if you're needing to push out code you can revert until you have time to fix it.

How to load local html file in alamofire?

I'm currently making a web application and need to load a local index.html file as the url, but i'm kinda lost. I'm familiar with the loadHTMLString from WebKit, but kinda lost when using alamofire.
I've tried to loadHTMLString in WebKit with webView with great
func registerShift() {
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
let parameters = [
"brugernavn": "user#email.dk",
"password": "testPass"
]
Alamofire.request(url, method: .post, parameters: parameters, encoding: URLEncoding.httpBody).responseString { response in
switch response.result {
case .success:
if let value = response.result.value {
print(value)
}
case .failure(let error):
print(error)
}
}
}
I expected the website to actually submit the form, however instead it printes the HTML of the local index.html. The local index.html file is just a simple form containing input (name = brugernavn) and input (name = password).

Swift 3: How to add or remove parameters in Request Body in ALamofire 4?

I am using Alamofire library for REST API calls. I have a Request Body of type
Dictionary(String, Any). There are few objects in the Request Body that are common for some APIs.
For eg: 1st API call contains following parameters in the request body.
var hotel = HotelParameter()
var food = foodParameter()
var address = addressParameter()
class RequestParameters: NSObject{
func parameter() -> NSDictionary {
var parameter : [String : Any] = [:]
parameter["hotels"] = hotel.params()
parameter["foodType"] = food.params()
parameter["address"] = address.params()
return parameter as! NSDictionary
}
Now in 2nd API call I have to pass only "hotels" and "address" in the RequestParameter.
My problem is: How to add or remove any extra parameter in the Alamofire Request Body?
Since I cannot add Request Body for 'n' number of Requests, there has to be a single RequestParameter which will get modified according to the api calls. There can be extra or single Parameter(s) in the Body.
Mostly "hotels" will be a common parameter for all Request Body.
I have tried a lot to solve this, But I get exception because it cannot parse some JSON response.
I have created functions to hit the api calls and I am passing the parameters like this.
var requestParam = RequestParamters()
Alamofire.request(url,
method: .post,
parameters: requestParam.parameter(),
encoding: JSONEncoding.default, headers: headers)
.responseJSON(completionHandler: { (data : DataResponse<Any>) in
I am not sure, I got your requirement right. But as per my understanding, you have to hit one API multiple times, and the parameter shall be different every time. So just write a method which'll take parameter as a method argument. Here is the sample code as per your requirement.
func getAllHotels(_ params:Dictionary, callback:#escaping (Dictionary<String, Any>, Error?)->Void)
{
let parameters: Parameters = params
Alamofire.request(baseUrl + "/getHotels", method: .post,parameters: parameters, encoding: URLEncoding.default).responseJSON { response in
debugPrint("All Response from API: \(response)")
switch response.result
{
case .success(let value):
callback(value as! Dictionary, nil)
case .failure(let error):
callback([:], error)
}
}
}
/** Now call the above method with your required parameters **/
I found out Two ways to do it.
Create an addExtraParams :[String : Any] = : type of Dictionary and add the key : value pair you need in this.
Create Requests functions for respective apis and just update the value of the required parameters using the object you get after logging.
For eg:
var user = response.object as! Person
var request = RequestParameters()
request.hotel.name = user.hotel_name
Update the values before the Alamofire request in the function that you have created.

Alamofire url encoded request parameter not getting added

I'm following Alamofire's CRUD and authorization section:
enum Router: URLRequestConvertible {
So what I want to accomplish is basically a simple PUT request which looks like this:
http://localhost:8080/rest/users/add?id=
So in my code I have:
let requestParam : [String : AnyObject] = ["id" : "\(SOMEID)"]
Alamofire.request(Router.AddUser(parameters: requestParam))
.validate()
.responseString { response in
switch response.result {
case .Success:
..
However, following my server doesn't get this id parameter.
Debugging the NSMutableURLRequest, I find that the id parameter isn't added.
case .AddUser(let parameters):
print(parameters)
let encodedURL = Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: parameters).0
print (encodedURL)
Console output:
["id": 5649fec6d4c662c573d39fb4]
{ URL: http://localhost:8080/rest/users/add }
This is really strange, because I had another method written almost identically but I wasn't getting the same issue.
Edit:
It turns out after some trials that it's because the method is PUT. If it was GET method then parameters were added correctly. Does anyone know why I can't put request parameters for PUT? Is this intentional?
In your router, why don't you use NSURLComponents to build your url and then return NSMutableURLRequest like that:
enum Router: URLRequestConvertible {
...
var URLRequest: NSMutableUrlRequest {
var urlComponents = NSURLComponents()
urlComponents.host = // something
urlComponents.scheme = // probably wanna use https
switch self {
case .AddUser(let parameters):
// set urlComponents.path here
urlComponents.query = parameters.queryString
// depending on your code you may want to check before force unwrapping URL below
return NSMutableUrlRequest(URL: urlComponents.URL!)
}
}
}
then you can extend dictionary with a computed property of type String.
Hope that helps!

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

Resources