部首:
let header = ["Content-Type" : "application/x-www-form-urlencoded", "Authorization" : "Basic " + self.basicAuth];
体:
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"
}
显然身体设置不正确,但我真的不知道为什么。我在其他应用程序中使用这段代码没有问题.... 同样的要求就像邮差中的魅力一样。邮递员的身体设置为x-www-form-urlencoded类型。 也许JSONSerialization错了?
答案 0 :(得分:0)
要使用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{"\($0)=\($1)"}.joined(separator: "&").data(using: .utf8)
//`body.map{"\($0)=\($1)"}.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{"\($0.wwwFormUrlencoded)=\($1.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()
}