如何快速发布http的特殊字符 [英] how to http post special chars in swift

查看:92
本文介绍了如何快速发布http的特殊字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下内容将电子邮件和密码发布到我的服务器(php脚本).我遇到的问题是密码包含一个特殊字符(特别是&符号),该字符似乎被剥夺了.我猜想是因为它认为要传递其分离变量.如何在不删除它的情况下传递此char?

I'm using the following to post an email and password to my server (php script). The problem I'm having is the password contains a special char (specifically the & symbol) which seems to be getting stripped. I presume because it thinks its separating variables being passed. How can I pass this char without it stripping it?

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)

推荐答案

您应该警惕使用NSURLComponents,因为NSURLQueryItem可能会百分比转义所讨论的字符&,而不会百分比转义-转义+字符(PHP将根据 queryItems文档所述:

You should be wary of using NSURLComponents because the NSURLQueryItem might percent-escape the character in question, the &, it doesn't percent-escape the + character (which PHP will interpret as a space in conformance with the W3C Specification for x-www-form-urlencoded). As the queryItems documentation says:

注意

RFC 3986 指定必须在以下内容的查询组件中对哪些字符进行百分比编码URL,但不解释如何解释这些字符.分隔键/值对的使用是一种常见的约定,但尚未通过规范进行标准化.因此,您可能会遇到遵循此约定的其他实现的互操作性问题.

RFC 3986 specifies which characters must be percent-encoded in the query component of a URL, but not how those characters should be interpreted. The use of delimited key-value pairs is a common convention, but isn't standardized by a specification. Therefore, you may encounter interoperability problems with other implementations that follow this convention.

一个潜在的互操作性问题的显着示例是如何处理加号(+)字符:

One notable example of potential interoperability problems is how the plus sign (+) character is handled:

根据RFC 3986,加号是查询中的有效字符,不需要进行百分比编码.但是,根据关于URI寻址的W3C建议,保留加号作为查询字符串(例如,?greeting=hello+world)中空格的简写形式.

According to RFC 3986, the plus sign is a valid character within a query, and doesn't need to be percent-encoded. However, according to the W3C recommendations for URI addressing, the plus sign is reserved as shorthand notation for a space within a query string (for example, ?greeting=hello+world).

如果您的值可能包含+字符,则可以为自己转义添加到URL查询的值留出一些替代方法:

This leaves a few alternatives for percent escaping the values you add to the query of the URL yourself if your value might include a + character:

  1. 您可以构建自己的要转义的字符CharacterSet,然后在Swift 3中使用addingPercentEncodingForURLQueryValue:

  1. You can build your own CharacterSet of characters to be escaped and then use addingPercentEncodingForURLQueryValue in 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-._~/?")
    }

}

  • Alamofire采取了类似的方法,但是从另一个方向进行处理,即获取.urlQueryAllowed字符集(该字符集很近,但不太正确),并取出了RFC 3986中标识的保留字符.斯威夫特3:

  • Alamofire takes a similar approach, but approaches this from the other direction, namely grabbing the .urlQueryAllowed character set (which is close, but not quite right), and takes out reserved characters identified in RFC 3986. In 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
    }
    

  • 然后,您可以使用以上代码对请求主体中的键和值进行百分比转义,例如:

    You could then use the above to percent escape the key and the value in the body of the request, for example:

    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)
    


    对于上述的Swift 2版本,请参见此答案的先前版本.

    这篇关于如何快速发布http的特殊字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆