Swift POST 请求发送一个空的正文

Posted

技术标签:

【中文标题】Swift POST 请求发送一个空的正文【英文标题】:Swift POST request sends an empty body 【发布时间】:2017-08-15 11:03:20 【问题描述】:

代码如下:

func makePOSTCall(endpoint: String, languageName: String) 
    guard let url = URL(string: endpoint) else 
        print("Could not create URL.")
        return
    

    let requestLang: [String: Any] = ["name": languageName]
    let requestBody = try? JSONSerialization.data(withJSONObject: requestLang)

    var urlRequest = URLRequest(url: url)
    urlRequest.httpBody = requestBody
    urlRequest.httpMethod = "POST"
    let session = URLSession.shared
    let task = session.dataTask(with: urlRequest) 

        data, response, error in
        guard let data = data, error == nil else 
            print(error?.localizedDescription ?? "No data")
            return
        

        let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
        if let responseJSON = responseJSON as? [String: Any] 
            print(responseJSON)
        

    
    task.resume()

这会向 Flask 发送一个 "name": "Go" JSON 字典。 Flask 应该将语言名称附加到一个数组并在响应中返回完整的数组。现在,这在我手动发送请求时有效,所以这不是 Flask 的错误。但是当我从 ios 发送上述内容时,我在烧瓶控制台中得到 request.json == None 。显然,我发送的是一个空的身体,但我不应该发送。知道我哪里出错了吗?

我把函数称为

@IBAction func pressedMakePOSTCall(_ sender: UIButton) 

    makePOSTCall(endpoint: "http://127.0.0.1:5000/lang", languageName: "Go")


我尝试添加一个斜杠,只是在控制台中得到一个 404。我发现的唯一与我类似的问题是:How to make HTTP Post request with JSON body in Swift,我的代码基本相同。

【问题讨论】:

你查过,JSONSerialization成功了吗,是requestBody不是nil?您也不应该将requestBody 定义为[String:Any],因为它的唯一值显然是String 类型,所以requestBody 应该是[String:String],但无论如何都不需要类型注释。 this works when I send the request manually 你这是什么意思?另外,你能检查一下requestBody的值吗? 这种行为可能有不同的问题。我认为您还应该验证您传输的数据是否具有正确的编码。你应该尝试设置你的内容类型。因为如果预期的内容类型是 x-www-form-urlencoded 并且您正在发送 application/json,则服务器不会像您预期的那样接收或处理数据。 @DávidPásztor,print(requestBody) 给出可选的(13 个字节)。如果序列化失败不应该抛出吗? 不,因为您使用的是try?,如果发生错误,它只会返回nil。仅当您使用嵌入在 do-catch 块中的 try 时才会引发错误,或者如果您使用 try! 并引发错误,则会出现不可恢复的运行时异常。但是,如果您的数据不为零,那么问题可能出在您的编码上。请包含来自其他来源(例如 Postman)的工作请求,以便我们可以在这里看到不同之处。 【参考方案1】:

@weissja19 是正确的,我需要将内容类型设置为 application/json。添加

urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")

修复了错误。现在代码可以正常工作了。

附:我无法捕捉到它,因为我使用应用程序 Paw 进行测试,它会自动设置内容类型。

【讨论】:

【参考方案2】:

您可能需要手动操作:

urlRequest.httpBody = "name=\(languageName)".data(using: .utf8)

使用 JSONSerialization 会使您的 POST 正文像 "name":"abc" 一样,您的服务器可能不支持它

【讨论】:

这正是我想做的。 Flask 服务器在请求正文中收到 json 时会对其进行解析。我已经用 Paw 发送了手动请求,它们都顺利通过了。

以上是关于Swift POST 请求发送一个空的正文的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Alamofire 4.0 中仅使用参数和正文在 swift 中使用 POST 方法发送请求?

Swift 2.0 POST 正文空

通过 HTTP 客户端 POST 一个空的正文

Swift 3 URLSession 发送空请求

使用 Express 获得一个空的身体

如何在 Swift 3 中使用 Alamofire 在 POST 请求中将给定的 JSON 作为参数发送?