2017-02-02 5 views
2

У меня есть URL, как этотКак заблокировать Alamofire от кодирования URL параметры

https://www.mysite/v1/search?N=4249847587+1798040122

Я использую Alamofire как тот

Almofire.request(.GET, "https://www.mysite/v1/search", parameters: ["N","4249847587+1798040122"], encoding: .URL) 

Logging запрос, я получаю

https://www.mysite/v1/search?N=4249847587%2B1798040122 

т.е.

"% 2B" вместо "+"

Но, мне нужно остаться с

"+"

Как я могу избежать этого кодирования с использованием Alamofire?

+1

https://github.com/Alamofire/Alamofire/pull/167/commits/570ed7e8fee36106c93a3251fbb1a97d818e7f09 – Sahil

+2

Нет, вы хотите, чтобы '+' был закодирован как '% 2B'. В противном случае сервер будет обрабатывать '+' как кодировку символа пробела. – rmaddy

+0

Спасибо, ребята, я решил проблему. Вы очень помогли мне –

ответ

2

Как правило, @rmaddy прав в своем комментарии. Но мы можем отключить эту кодировку как забавное упражнение.

Для этого нам потребуется использовать пользовательский кодировщик. Alamofire поддерживает любой пользовательский кодировщик, который реализует протокол ParameterEncoding вместо encoding: .URL.

Так в можно использовать немного копии & вставленного код из оригинального Alamofire кодового и создать собственный кодировщик

public struct NOURLEncoding: ParameterEncoding { 

    //protocol implementation 
    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { 
     var urlRequest = try urlRequest.asURLRequest() 

     guard let parameters = parameters else { return urlRequest } 

     if HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET") != nil { 
      guard let url = urlRequest.url else { 
       throw AFError.parameterEncodingFailed(reason: .missingURL) 
      } 

      if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty { 
       let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters) 
       urlComponents.percentEncodedQuery = percentEncodedQuery 
       urlRequest.url = urlComponents.url 
      } 
     } 

     return urlRequest 
    } 

    //append query parameters 
    private func query(_ parameters: [String: Any]) -> String { 
     var components: [(String, String)] = [] 

     for key in parameters.keys.sorted(by: <) { 
      let value = parameters[key]! 
      components += queryComponents(fromKey: key, value: value) 
     } 

     return components.map { "\($0)=\($1)" }.joined(separator: "&") 
    } 

    //Alamofire logic for query components handling 
    public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] { 
     var components: [(String, String)] = [] 

     if let dictionary = value as? [String: Any] { 
      for (nestedKey, value) in dictionary { 
       components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value) 
      } 
     } else if let array = value as? [Any] { 
      for value in array { 
       components += queryComponents(fromKey: "\(key)[]", value: value) 
      } 
     } else if let value = value as? NSNumber { 
      if value.isBool { 
       components.append((escape(key), escape((value.boolValue ? "1" : "0")))) 
      } else { 
       components.append((escape(key), escape("\(value)"))) 
      } 
     } else if let bool = value as? Bool { 
      components.append((escape(key), escape((bool ? "1" : "0")))) 
     } else { 
      components.append((escape(key), escape("\(value)"))) 
     } 

     return components 
    } 

    //escaping function where we can select symbols which we want to escape 
    //(I just removed + for example) 
    public func escape(_ string: String) -> String { 
     let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 
     let subDelimitersToEncode = "!$&'()*,;=" 

     var allowedCharacterSet = CharacterSet.urlQueryAllowed 
     allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)") 

     var escaped = "" 

     escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string 

     return escaped 
    } 

} 

extension NSNumber { 
    fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) } 
} 

Я не знаю, почему это может быть полезно. Но пользовательское кодирование может быть легко добавлено. Теперь вы можете просто использовать запрос Alamofire с нашим новым кодировщика

Alamofire.request("http://www.mysite/v1/search", method: .get, parameters: ["N": "4249847587+1798040122"], encoding: NOURLEncoding()) 
1

Хотя вопрос был дан ответ только для тех, кто новичок в быстрых и, возможно, с использованием Alamofire впервые и сталкиваются с проблемами.

Здесь

BaseUrl = "https://www.baseUrl.com/",

путь = "пользователь/ничего/статус? Ток = Single" Это то, что я сделал (Swift 3,0, Alamofire V4.4)

let completeUrl = baseUrl.appending(path) 
let urlWithoutPercent = completeUrl.removingPercentEncoding 
let finalUrl = URL(string: urlWithoutPercent!) 
var URLRequest = Foundation.URLRequest(url: finalUrl!) 

или

let wholeURL = baseUrl.appending(path) 
let urlwithPercent = wholeURL.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) 
var URLRequest = Foundation.URLRequest(url: URL(string: urlwithPercent!)!) 

Теперь история является:

Мой URL получал переустроенные в чем-то вроде этого:

https://www.baseUrl.com/user/anything/status% 3F ток = Single

ответ придет в 403. после поиска в Интернете около 4 часов я не мог найти простую и небольшую ошибку. Затем, удалив процентное кодирование, решила проблему. Кроме того, это неправильный подход, как сказано в комментариях @rmaddy.

И это относится ко всей специальной кодировке символов Вне зависимости от ли это вопросительный знак, восклицательный знак или что-нибудь ..

Надеется, что это поможет кому-то.

+0

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: может случиться так, что ваши другие вызовы api могут не дать желаемого ответа ... Короче говоря, они могут потерпеть неудачу .. этот трюк работает только с параметрами url, имеющими специальные символы. –