如何阻止 Alamofire 编码 URL 参数
Posted
技术标签:
【中文标题】如何阻止 Alamofire 编码 URL 参数【英文标题】:How to block Alamofire from encoding of URL parameters 【发布时间】:2017-02-02 18:58:54 【问题描述】:我有一个这样的网址
https://www.mysite/v1/search?N=4249847587+1798040122
我就是这样用 Alamofire 的
Almofire.request(.GET, "https://www.mysite/v1/search", parameters: ["N","4249847587+1798040122"], encoding: .URL)
记录请求,我收到
https://www.mysite/v1/search?N=4249847587%2B1798040122
即
“%2B”而不是“+”
但是,我需要留下来
“+”
如何避免使用 Alamofire 进行编码?
【问题讨论】:
github.com/Alamofire/Alamofire/pull/167/commits/… 不,您希望将+
编码为%2B
。否则服务器会将+
视为空格字符的编码。
谢谢各位,我已经解决了这个问题。你帮了我很多
【参考方案1】:
通常@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())
【讨论】:
【参考方案2】:虽然这个问题只针对那些不熟悉 swift 并且可能是第一次使用 Alamofire 并面临问题的人。
这里,
baseUrl = "https://www.baseUrl.com/",
path = "用户/任何东西/状态?当前=单身" 这就是我所做的(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!)!)
现在的故事是:
我的网址被转换成这样的:
https://www.baseUrl.com/user/anything/status%3Fcurrent=Single
响应是 403。 在网上搜索了大约 4 个小时后,我找不到一个简单而小的修复程序。然后通过删除百分比编码解决了这个问题。 此外,这不是 @rmaddy 在 cmets 中所说的正确方法。
这适用于所有特殊字符编码,无论是问号、感叹号还是其他任何东西..
希望对某人有所帮助。
【讨论】:
免责声明:您的其他 api 调用可能不会给出所需的响应......总之它们可能会失败......这个技巧只适用于具有特殊字符参数的 url。以上是关于如何阻止 Alamofire 编码 URL 参数的主要内容,如果未能解决你的问题,请参考以下文章
使用 SwiftyJSON 对 Alamofire GET 参数进行 URL 编码