gpt4 book ai didi

swift - 在 NSMutableURLRequest 中设置主体不起作用

转载 作者:行者123 更新时间:2023-11-30 12:38:22 24 4
gpt4 key购买 nike

标题:

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 参数是必需字段,并且必须是非空字符串。",
“错误”:“无效请求”
}

显然主体设置不正确,但我真的不知道为什么。我在其他应用程序中使用这段代码没有问题......同样的请求在 Postman 中就像魅力一样起作用。 postman 中的正文设置为 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{"\($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()
}

关于swift - 在 NSMutableURLRequest 中设置主体不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42578396/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com