发送 post 数据 nsurlsession
Sending post data nsurlsession
您好,我正在尝试在操场上使用 NSURLSession 在 swift 中复制以下 curl 命令。
curl -k -i -H "Accept: application/json" -H "X-Application: " -X POST -d 'username=&password=' https://address.com/api/login
这是我目前所知道的。我挣扎的地方是我不确定如何发送 post 数据,例如:'username=&password='。任何帮助将不胜感激。
提前致谢。
import Foundation
import XCPlayground
// Let asynchronous code run
XCPSetExecutionShouldContinueIndefinitely()
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.HTTPAdditionalHeaders = ["Accept" : "application/json", "X-Application" : "<AppKey>"]
let session = NSURLSession(configuration: config)
var running = false
let url = NSURL(string: "https://address.com/api/login")
let task = session.dataTaskWithURL(url!) {
(let data, let response, let error) in
if let httpResponse = response as? NSHTTPURLResponse {
let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
println(dataString)
}
running = false
}
running = true
task.resume()
也许这有帮助,我用它来发送 post 数据:
var paramString = ""
var request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
request.HTTPMethod = "POST"
var user = "MyUsername".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
var pass = "MyPassword".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
paramString = "username="+user!+"&password="+pass!
request.HTTPBody = paramString.dataUsingEncoding(NSUTF8StringEncoding)
let conf: NSURLSessionConfiguration = NSURLSession.sharedSession().configuration
let session = NSURLSession(configuration: conf)
session.dataTaskWithRequest(request) {
data, response, error in
let resp = NSString(data: data, encoding: NSUTF8StringEncoding)
}.resume()
NSUTF8StringEncoding 可以随便替换
您可以创建一个可变 URLRequest
并设置 httpBody
。但是您还应该对 username
的值进行百分比转义,更重要的是,对 password
.
的值进行转义
所以,想象一下您的请求是这样创建的:
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = ["Accept" : "application/json", "X-Application" : "<AppKey>", "Content-Type" : "application/x-www-form-urlencoded"]
let session = URLSession(configuration: config)
let url = URL(string: "https://identitysso.betfair.com/api/login")!
var request = URLRequest(url: url)
request.setBodyContent(["username": username, "password": password])
let task = session.dataTask(with: request) { data, response, error in
// make sure there wasn't a fundamental networking error
guard let data = data, let response = response as? HTTPURLResponse, error == nil else {
print(error ?? "Unknown error")
return
}
// if you're going to check for NSHTTPURLResponse, then do something useful
// with it, e.g. see if server status code indicates that everything is OK
guard 200 ..< 300 ~= response.statusCode else {
print("statusCode not 2xx; was \(response.statusCode)")
return
}
// since you set `Accept` to JSON, I'd assume you'd want to parse it;
// In Swift 4 and later, use JSONDecoder; in Swift 3 use JSONSerialization
do {
if let responseObject = try JSONSerialization.jsonObject(with: data) as? [String: AnyObject] {
print(responseObject)
}
} catch let parseError {
print(parseError)
print(String(data: data, encoding: .utf8) ?? data as NSData)
}
}
task.resume()
所以问题是 setBodyContent
如何在给定字典的情况下构建请求正文。是的,您想对不在未保留字符集中的任何内容进行百分号转义,但遗憾的是 CharacterSet.urlQueryAllowed
不能胜任这项工作。所以你可以这样做:
extension URLRequest {
/// Populate the HTTPBody of `application/x-www-form-urlencoded` request
///
/// - parameter parameters: A dictionary of keys and values to be added to the request
mutating func setBodyContent(_ parameters: [String : String]) {
let parameterArray = parameters.map { (key, value) -> String in
let encodedKey = key.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
let encodedValue = value.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
return "\(encodedKey)=\(encodedValue)"
}
httpBody = parameterArray
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
/// Character set containing characters allowed in query value as outlined in RFC 3986.
///
/// 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.
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
return allowed
}()
}
此外,我通常使用更复杂的 setBodyContent
,它也接受数字、布尔值和日期类型,但我不想离题太远,即如何正确构建请求两个字符串 key/values 对。
对于 Swift 2 版本,请参阅 previous revision of this answer。
您好,我正在尝试在操场上使用 NSURLSession 在 swift 中复制以下 curl 命令。
curl -k -i -H "Accept: application/json" -H "X-Application: " -X POST -d 'username=&password=' https://address.com/api/login
这是我目前所知道的。我挣扎的地方是我不确定如何发送 post 数据,例如:'username=&password='。任何帮助将不胜感激。
提前致谢。
import Foundation
import XCPlayground
// Let asynchronous code run
XCPSetExecutionShouldContinueIndefinitely()
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.HTTPAdditionalHeaders = ["Accept" : "application/json", "X-Application" : "<AppKey>"]
let session = NSURLSession(configuration: config)
var running = false
let url = NSURL(string: "https://address.com/api/login")
let task = session.dataTaskWithURL(url!) {
(let data, let response, let error) in
if let httpResponse = response as? NSHTTPURLResponse {
let dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
println(dataString)
}
running = false
}
running = true
task.resume()
也许这有帮助,我用它来发送 post 数据:
var paramString = ""
var request:NSMutableURLRequest = NSMutableURLRequest(URL:url)
request.HTTPMethod = "POST"
var user = "MyUsername".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
var pass = "MyPassword".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
paramString = "username="+user!+"&password="+pass!
request.HTTPBody = paramString.dataUsingEncoding(NSUTF8StringEncoding)
let conf: NSURLSessionConfiguration = NSURLSession.sharedSession().configuration
let session = NSURLSession(configuration: conf)
session.dataTaskWithRequest(request) {
data, response, error in
let resp = NSString(data: data, encoding: NSUTF8StringEncoding)
}.resume()
NSUTF8StringEncoding 可以随便替换
您可以创建一个可变 URLRequest
并设置 httpBody
。但是您还应该对 username
的值进行百分比转义,更重要的是,对 password
.
所以,想象一下您的请求是这样创建的:
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = ["Accept" : "application/json", "X-Application" : "<AppKey>", "Content-Type" : "application/x-www-form-urlencoded"]
let session = URLSession(configuration: config)
let url = URL(string: "https://identitysso.betfair.com/api/login")!
var request = URLRequest(url: url)
request.setBodyContent(["username": username, "password": password])
let task = session.dataTask(with: request) { data, response, error in
// make sure there wasn't a fundamental networking error
guard let data = data, let response = response as? HTTPURLResponse, error == nil else {
print(error ?? "Unknown error")
return
}
// if you're going to check for NSHTTPURLResponse, then do something useful
// with it, e.g. see if server status code indicates that everything is OK
guard 200 ..< 300 ~= response.statusCode else {
print("statusCode not 2xx; was \(response.statusCode)")
return
}
// since you set `Accept` to JSON, I'd assume you'd want to parse it;
// In Swift 4 and later, use JSONDecoder; in Swift 3 use JSONSerialization
do {
if let responseObject = try JSONSerialization.jsonObject(with: data) as? [String: AnyObject] {
print(responseObject)
}
} catch let parseError {
print(parseError)
print(String(data: data, encoding: .utf8) ?? data as NSData)
}
}
task.resume()
所以问题是 setBodyContent
如何在给定字典的情况下构建请求正文。是的,您想对不在未保留字符集中的任何内容进行百分号转义,但遗憾的是 CharacterSet.urlQueryAllowed
不能胜任这项工作。所以你可以这样做:
extension URLRequest {
/// Populate the HTTPBody of `application/x-www-form-urlencoded` request
///
/// - parameter parameters: A dictionary of keys and values to be added to the request
mutating func setBodyContent(_ parameters: [String : String]) {
let parameterArray = parameters.map { (key, value) -> String in
let encodedKey = key.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
let encodedValue = value.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)!
return "\(encodedKey)=\(encodedValue)"
}
httpBody = parameterArray
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
/// Character set containing characters allowed in query value as outlined in RFC 3986.
///
/// 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.
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode)
return allowed
}()
}
此外,我通常使用更复杂的 setBodyContent
,它也接受数字、布尔值和日期类型,但我不想离题太远,即如何正确构建请求两个字符串 key/values 对。
对于 Swift 2 版本,请参阅 previous revision of this answer。