我正在使用以下内容将电子邮件和密码发布到我的服务器(php脚本)。我遇到的问题是密码包含一个特殊字符(特别是&符号),该字符似乎被剥夺了。我猜想是因为它认为要传递其分离变量。如何在不删除它的情况下传递此char?
let myURL = NSURL(string: "my script url here")
let request = NSMutableURLRequest(URL: myURL!)
request.HTTPMethod = "POST"
let postString = "email=\(userEmailText)&password=\(userPasswordText)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
Run Code Online (Sandbox Code Playgroud)
您应该警惕使用它,NSURLComponents因为NSURLQueryItem可能会百分号转换所讨论的字符&,而不会百分号转换+字符(PHP会将其解释为符合W3C规范x-www-form-urlencoded的空格)。由于该queryItems文件说:
注意
RFC 3986指定必须在URL的查询组件中对哪些字符进行百分比编码,但不指定应如何解释这些字符。分隔键/值对的使用是一种常见的约定,但尚未由规范进行标准化。因此,您可能会遇到遵循此约定的其他实现的互操作性问题。
潜在的互操作性问题的一个著名示例是如何处理加号(
+)字符:根据RFC 3986,加号是查询中的有效字符,不需要进行百分比编码。但是,根据W3C关于URI寻址的建议,加号保留为查询字符串(例如
?greeting=hello+world)中空格的简写形式。
如果您的值可能包含+字符,则可以为百分比转义您自己添加到URL查询的值留出几种选择:
您可以构建自己CharacterSet的要转义的字符,然后addingPercentEncodingForURLQueryValue在Swift 3中使用:
extension String {
/// Returns a new string made from the `String` by replacing all characters not in the unreserved
/// character set (as defined by RFC3986) with percent encoded characters.
func addingPercentEncodingForURLQueryValue() -> String? {
let allowedCharacters = CharacterSet.urlQueryValueAllowed()
return addingPercentEncoding(withAllowedCharacters: allowedCharacters)
}
}
extension CharacterSet {
/// Returns the character set for characters allowed in the individual parameters within a query URL component.
///
/// The query component of a URL is the component immediately following a question mark (?).
/// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query
/// component is `key1=value1`. The individual parameters of that query would be the key `key1`
/// and its associated value `value1`.
///
/// According to RFC 3986, the set of unreserved characters includes
///
/// `ALPHA / DIGIT / "-" / "." / "_" / "~"`
///
/// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters
/// for the sake of compatibility with some erroneous implementations, so this routine also allows those
/// to pass unescaped.
static func urlQueryValueAllowed() -> CharacterSet {
return CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~/?")
}
}
Run Code Online (Sandbox Code Playgroud)Alamofire采取了类似的方法,但是从另一个方向进行处理,即获取.urlQueryAllowed字符集(很接近,但不太正确),并取出RFC 3986中标识的保留字符。在Swift 3中:
/// Returns a percent-escaped string following RFC 3986 for a query string key or value.
///
/// RFC 3986 states that the following characters are "reserved" characters.
///
/// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
/// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
///
/// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
/// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
/// should be percent-escaped in the query string.
///
/// - parameter string: The string to be percent-escaped.
///
/// - returns: The percent-escaped string.
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 = ""
//==========================================================================================================
//
// Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few
// hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no
// longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more
// info, please refer to:
//
// - https://github.com/Alamofire/Alamofire/issues/206
//
//==========================================================================================================
if #available(iOS 8.3, *) {
escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
} else {
let batchSize = 50
var index = string.startIndex
while index != string.endIndex {
let startIndex = index
let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
let range = startIndex..<endIndex
let substring = string.substring(with: range)
escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring
index = endIndex
}
}
return escaped
}
Run Code Online (Sandbox Code Playgroud)然后,您可以使用上述代码对请求正文中的键和值进行百分比转义,例如:
let parameters = ["email" : email, "password" : password]
request.httpBody = parameters
.map { (key, value) in
let escapedKey = key.addingPercentEncodingForURLQueryValue()!
let escapedValue = value.addingPercentEncodingForURLQueryValue()!
return "\(escapedKey)=\(escapedValue)"
}
.joined(separator: "&")
.data(using: .utf8)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1716 次 |
| 最近记录: |