在 NSMutableURLRequest 中设置 body 不起作用
set body in NSMutableURLRequest doesn´t work
Header:
let header = ["Content-Type" : "application/x-www-form-urlencoded", "Authorization" : "Basic " + self.basicAuth];
Body:
var body : [String : AnyObject] = [:];
let body = ["grant_type" : "client_credentials", "scope" : "MessageSender"];
请求和序列化:
private func makeHTTPPostRequest(path: String, header: [String : String], body: [String: AnyObject], onCompletion: @escaping ServiceResponse) {
let request = NSMutableURLRequest(url: NSURL(string: path)! as URL)
// Set the method to POST
request.httpMethod = "POST"
do {
// Set the POST body for the request
let jsonBody = try JSONSerialization.data(withJSONObject: body, options: .prettyPrinted)
request.httpBody = jsonBody
let session = URLSession.shared
request.allHTTPHeaderFields = header;
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if let httpResponse = response as? HTTPURLResponse {
if let jsonData = data {
let json:JSON = JSON(data: jsonData)
print(response)
print(json)
onCompletion(json,httpResponse, error as NSError?)
} else {
onCompletion(JSON.null,HTTPURLResponse.init(), error as NSError?)
}
}
})
task.resume()
} catch {
onCompletion(JSON.null,HTTPURLResponse.init(), nil)
}
}
}
请求完成后,它会触发 400 响应
{
"error_description" : "grant_type parameter is requiered field and it has to be non empty string.",
"error" : "invalid_request"
}
显然 body 设置不正确,但我真的不知道为什么。我在其他应用程序中使用这段代码没有问题...。
同样的请求在 Postman 中就像魅力一样。邮递员中的 body 设置为类型 x-www-form-urlencoded。
也许 JSONSerialization 是错误的?
要使用 Content-Type: application/x-www-form-urlencoded;
发送 POST 请求,您需要创建一个 URL 类似查询的字符串,然后将其转换为数据。您的代码或任何 Swift 标准库函数不具备该功能。可能需要自己写,或者找合适的第三方库。 (当然JSONSerialization
不适合这里,String不是JSON。)
给定一个 Dictionary<String, String>
,你可以这样做:
var body: [String: String] = [:]
body = ["grant_type": "client_credentials", "scope": "MessageSender"]
(简化...)
request.httpBody = body.map{"\([=11=])=\()"}.joined(separator: "&").data(using: .utf8)
//`body.map{"\([=11=])=\()"}.joined(separator: "&")` -> grant_type=client_credentials&scope=MessageSender
(严格...4.10.22.6 URL-encoded form data)
extension CharacterSet {
static let wwwFormUrlencodedAllowed = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._*" + "+")
}
extension String {
var wwwFormUrlencoded: String {
return self
.replacingOccurrences(of: " ", with: "+")
.addingPercentEncoding(withAllowedCharacters: .wwwFormUrlencodedAllowed)!
}
}
class HTTPBody {
static func wwwFormUrlencodedData(withDictionary dict: [String: String]) -> Data {
return body
.map{"\([=12=].wwwFormUrlencoded)=\(.wwwFormUrlencoded)"}
.joined(separator: "&").data(using: .utf8)!
}
}
request.httpBody = HTTPBody.wwwFormUrlencodedData(withDictionary: body)
(请记住,没有多少服务器将收到的表单数据解释为严格生成的。)
此外,在这种情况下这不是关键问题,但您最好使用 Swift 类 而不是 NS-
某物:
typealias ServiceResponse = (JSON, HTTPURLResponse?, Error?)->Void
private func makeHTTPPostRequest(path: String, header: [String : String], body: [String: String], onCompletion: @escaping ServiceResponse) {
var request = URLRequest(url: URL(string: path)!)
// Set the method to POST
request.httpMethod = "POST"
// Set the POST body for the request (assuming your server likes strict form data)
request.httpBody = HTTPBody.wwwFormUrlencodedData(withDictionary: body)
let session = URLSession.shared
request.allHTTPHeaderFields = header;
let task = session.dataTask(with: request, completionHandler: {data, response, error -> Void in
if let httpResponse = response as? HTTPURLResponse {
if let jsonData = data {
let json:JSON = JSON(data: jsonData)
print(response)
print(json)
onCompletion(json, httpResponse, error)
} else {
onCompletion(JSON.null, httpResponse, error)
}
}
})
task.resume()
}
Header:
let header = ["Content-Type" : "application/x-www-form-urlencoded", "Authorization" : "Basic " + self.basicAuth];
Body:
var body : [String : AnyObject] = [:];
let body = ["grant_type" : "client_credentials", "scope" : "MessageSender"];
请求和序列化:
private func makeHTTPPostRequest(path: String, header: [String : String], body: [String: AnyObject], onCompletion: @escaping ServiceResponse) {
let request = NSMutableURLRequest(url: NSURL(string: path)! as URL)
// Set the method to POST
request.httpMethod = "POST"
do {
// Set the POST body for the request
let jsonBody = try JSONSerialization.data(withJSONObject: body, options: .prettyPrinted)
request.httpBody = jsonBody
let session = URLSession.shared
request.allHTTPHeaderFields = header;
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if let httpResponse = response as? HTTPURLResponse {
if let jsonData = data {
let json:JSON = JSON(data: jsonData)
print(response)
print(json)
onCompletion(json,httpResponse, error as NSError?)
} else {
onCompletion(JSON.null,HTTPURLResponse.init(), error as NSError?)
}
}
})
task.resume()
} catch {
onCompletion(JSON.null,HTTPURLResponse.init(), nil)
}
}
}
请求完成后,它会触发 400 响应
{
"error_description" : "grant_type parameter is requiered field and it has to be non empty string.",
"error" : "invalid_request"
}
显然 body 设置不正确,但我真的不知道为什么。我在其他应用程序中使用这段代码没有问题...。 同样的请求在 Postman 中就像魅力一样。邮递员中的 body 设置为类型 x-www-form-urlencoded。 也许 JSONSerialization 是错误的?
要使用 Content-Type: application/x-www-form-urlencoded;
发送 POST 请求,您需要创建一个 URL 类似查询的字符串,然后将其转换为数据。您的代码或任何 Swift 标准库函数不具备该功能。可能需要自己写,或者找合适的第三方库。 (当然JSONSerialization
不适合这里,String不是JSON。)
给定一个 Dictionary<String, String>
,你可以这样做:
var body: [String: String] = [:]
body = ["grant_type": "client_credentials", "scope": "MessageSender"]
(简化...)
request.httpBody = body.map{"\([=11=])=\()"}.joined(separator: "&").data(using: .utf8)
//`body.map{"\([=11=])=\()"}.joined(separator: "&")` -> grant_type=client_credentials&scope=MessageSender
(严格...4.10.22.6 URL-encoded form data)
extension CharacterSet {
static let wwwFormUrlencodedAllowed = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._*" + "+")
}
extension String {
var wwwFormUrlencoded: String {
return self
.replacingOccurrences(of: " ", with: "+")
.addingPercentEncoding(withAllowedCharacters: .wwwFormUrlencodedAllowed)!
}
}
class HTTPBody {
static func wwwFormUrlencodedData(withDictionary dict: [String: String]) -> Data {
return body
.map{"\([=12=].wwwFormUrlencoded)=\(.wwwFormUrlencoded)"}
.joined(separator: "&").data(using: .utf8)!
}
}
request.httpBody = HTTPBody.wwwFormUrlencodedData(withDictionary: body)
(请记住,没有多少服务器将收到的表单数据解释为严格生成的。)
此外,在这种情况下这不是关键问题,但您最好使用 Swift 类 而不是 NS-
某物:
typealias ServiceResponse = (JSON, HTTPURLResponse?, Error?)->Void
private func makeHTTPPostRequest(path: String, header: [String : String], body: [String: String], onCompletion: @escaping ServiceResponse) {
var request = URLRequest(url: URL(string: path)!)
// Set the method to POST
request.httpMethod = "POST"
// Set the POST body for the request (assuming your server likes strict form data)
request.httpBody = HTTPBody.wwwFormUrlencodedData(withDictionary: body)
let session = URLSession.shared
request.allHTTPHeaderFields = header;
let task = session.dataTask(with: request, completionHandler: {data, response, error -> Void in
if let httpResponse = response as? HTTPURLResponse {
if let jsonData = data {
let json:JSON = JSON(data: jsonData)
print(response)
print(json)
onCompletion(json, httpResponse, error)
} else {
onCompletion(JSON.null, httpResponse, error)
}
}
})
task.resume()
}