使用 Swift URLSession 将标头传递给 URL

Posted

技术标签:

【中文标题】使用 Swift URLSession 将标头传递给 URL【英文标题】:Passing headers to URL with Swift URLSession 【发布时间】:2019-10-23 08:19:32 【问题描述】:

我不想分享实际链接,因为它可能包含一些私人信息,所以如果它不起作用,请不要感到惊讶。

我有一个如下所示的链接:www.somelink.com/stuff/searchmembers?member=John

还有一些我需要传递的标头,例如Login: Admin, Password: Admin

当我使用this site 时,一切似乎都运行良好,我放置了链接,将其设为 GET 并将标题放入 key:value 格式,结果我得到了所有成员的列表,但我该怎么做与 URLSession 一样吗?这是我目前拥有的,我什么都没有。我在那里做错了什么?

func getAllMembers(urlString: String) 

    guard let url = URL(string: urlString) else  return 

    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue("Admin", forHTTPHeaderField: "Login")
    request.setValue("Admin", forHTTPHeaderField: "Password")
    request.httpBody = "member=John".data(using: .utf8)!


    URLSession.shared.dataTask(with: request)  (data, response, error) in
        print(response)
        print(data)
    .resume()

【问题讨论】:

request.httpBody = "member=John".data(using: .utf8)!,这不是在您的网址末尾添加它。我不熟悉 Reqbin,也没有赞助 POSTMAN,但后来的解决方案可以为您生成 Swift 代码(不漂亮),但理解足以发现您和他们之间的问题。 你用邮递员试过这个吗? 我不知道 Postman,但它确实有效。谢谢! 【参考方案1】:

这是你做错了:

您的member=John 实际上是一个URL 查询参数。通常,URL 请求将查询参数作为 URL 字符串本身的一部分,而不是 httpbody。


快速而肮脏的解决方案:

如果你删除,你应该很高兴

request.httpBody = "member=John".data(using: .utf8)!

而是将整个 "www.somelink.com/stuff/searchmembers?member=John" 传递给您的 getAllMembers(urlString:) 函数。


更好的解决方案:

假设 John 的用户名是 j o h n。您的函数不会超过第一个 guard,因为空格不是有效的 URL 字符串字符。

我喜欢使用URLComponents,因为它省去了处理空格等的麻烦。

我会这样写你的函数:

func getJohnMember(urlString: String) 

    //URLComponents to the rescue!
    var urlBuilder = URLComponents(string: urlString)
    urlBuilder?.queryItems = [
        URLQueryItem(name: "member", value: "j o h n")
    ]

    guard let url = urlBuilder?.url else  return 

    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue("Admin", forHTTPHeaderField: "Login")
    request.setValue("Admin", forHTTPHeaderField: "Password")


    URLSession.shared.dataTask(with: request)  (data, response, error) in
        print(response)
        print(String(data: data, encoding: .utf8)) //Try this too!
    .resume()

为了清楚起见,我只会将"www.somelink.com/stuff/searchmembers" 传递给第一个参数。

现在如果我在guard let 之后到print(url),我会得到

www.somelink.com/stuff/searchmembers?member=j%20o%20h%20n

这样更容易,不是吗?

【讨论】:

【参考方案2】:

member=John 是一个 URL 查询参数,不是请求正文的一部分。所以你需要将它添加到 URL 本身。

func getAllMembers(urlString: String) 
    guard let url = URL(string: "\(urlString)?member=John") else  return 

    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue("Admin", forHTTPHeaderField: "Login")
    request.setValue("Admin", forHTTPHeaderField: "Password")


    URLSession.shared.dataTask(with: request)  (data, response, error) in
        print(response)
        print(data)
    .resume()

【讨论】:

URLQueryItem 是添加该成员名称的正确方法,而不是附加到 url。接受的答案正确地涵盖了这一点。这会起作用,但是......“这没有错,但我们只是不这样做” - Gordon。

以上是关于使用 Swift URLSession 将标头传递给 URL的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 来自URLSession任务的TableView数据源

将 URLSession 更新为 swift 3 抛出错误

Swift 3 ObjectMapper - 将 URLSession 结果转换为 Map 对象失败

URLSession 配置的标头设置仅适用于 PUT,不适用于 POST

如何使用 Swift URLSession 通过 REST api 将图像和其他参数作为表单数据发布?

Swift UrlSession 在 UrlSession 中不起作用