如何在Swift中转义HTTP参数

我正在尝试发送到HTTP服务器

顺便说一句,这是我的代码:

func sendPostToUrl(url:String, withParams params: [String: String?] ) { var request = NSMutableURLRequest(URL: NSURL(string: url)!) var session = NSURLSession.sharedSession() request.HTTPMethod = "POST" var err: NSError? var bodyData = "" for (key,value) in params{ if (value==nil){ continue } let scapedKey = key.stringByAddingPercentEncodingWithAllowedCharacters( .URLHostAllowedCharacterSet())! let scapedValue = value!.stringByAddingPercentEncodingWithAllowedCharacters( .URLHostAllowedCharacterSet())! bodyData += "\(scapedKey)=\(scapedValue)&" } request.HTTPBody = bodyData.dataUsingEncoding (NSUTF8StringEncoding, allowLossyConversion: true) var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in println("Response: \(response)") let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) println("Data: \(dataString)") }) task.resume() } 

它的作品,但并不完美。 如果我这样调用函数:

  client.sendPostToUrl("http://novagecko.com/tests/test.php", withParams: ["hello":"world","inject":"param1=value1&param2=value2"]); 

服务器检测到3个后期字段(用键helloinjectparam2 )而不是2。

我怎样才能摆脱关键和价值?

还有什么我可以做的改进方法?

如果您可以定位iOS 8(感谢@Rob),请使用NSURLComponents转义您的参数:

 import Foundation func encodeParameters(#params: [String: String]) -> String { var queryItems = map(params) { NSURLQueryItem(name:$0, value:$1)} var components = NSURLComponents() components.queryItems = queryItems return components.percentEncodedQuery ?? "" } 

现在encodeParameters(params:["hello":"world","inject":"param1=value1&param2=value2"])像你期望的那样返回hello=world&inject=param1%3Dvalue1%26param2%3Dvalue2

否则,创build字符集的最好方法就是让你正确地转义你的值:

 var safeCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() safeCharacterSet.removeCharactersInString("&=") 

并看到@ rintaro的答案正确使用filter/地图来执行一个很好的编码方式。

看来, NSCharacterSet没有相关的设置。

所以,添加这个

 extension NSCharacterSet { class func URLUnreservedCharacterSet() -> NSCharacterSet { return self(charactersInString: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.~") } } 

然后

 var bodyData = "" var safeCharacterSet = NSCharacterSet.URLUnreservedCharacterSet() for (key,value) in params{ if (value==nil){ continue } let scapedKey = key.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)! let scapedValue = value!.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)! bodyData += "\(scapedKey)=\(scapedValue)&" } 

以下是@ Rob在评论中的build议,下面是一个mapjoin示例:

 let params:[String:String?] = ["fubar":nil, "hello":"world", "inject":"param1=value1&param2=value2"] let safeCharacterSet = NSCharacterSet.URLUnreservedCharacterSet() let pairs = filter(params, {$1 != nil}).map { (key, value) -> String in let _key = key.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)! let _val = value!.stringByAddingPercentEncodingWithAllowedCharacters(safeCharacterSet)! return _key + "=" + _val } let bodyData = "&".join(pairs) 

这是更好的,因为没有结果。

    Interesting Posts