Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing headers to URL with Swift URLSession

I don't feel like sharing the actual link as it may have some private information so don't be surprised if it doesn't work.

I have a link that looks like this: www.somelink.com/stuff/searchmembers?member=John

And some headers that I need to pass, like Login: Admin, Password: Admin

When I use this site everything seems to be working just fine, I put the link, make it GET and put headers in key:value format and as a result I get the list of all members, but how can I do the same with URLSession? Here's what I currently have and I don't get anything at all. What am I doing wrong there?

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()
}
like image 859
Mikara Avatar asked Oct 23 '19 08:10

Mikara


2 Answers

Here is What You're Doing Wrong:

Your member=John is actually a URL query parameter. In general, URL requests have query parameters as a part of the URL string itself and not the httpbody.


Quick and Dirty Solution:

You should be good to go if you remove

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

and instead pass the whole "www.somelink.com/stuff/searchmembers?member=John" into your getAllMembers(urlString:) function.


A Better Solution:

Let's say John's username is j o h n. Your function wouldn't make it past that first guard because spaces aren't valid URL string characters.

I like to use URLComponents because it saves me the trouble of having to handle spaces and such.

Here's how I'd write your function:

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()
}

Just to be clear, I would pass just "www.somelink.com/stuff/searchmembers" into the first parameter.

Now if I were to print(url) after the guard let, I'd get

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

Much easier this way, no?

like image 133
Xavier L. Avatar answered Nov 10 '22 18:11

Xavier L.


That member=John is a URL-query parameter, not part of the request body. So you need to add it to the URL itself.

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()
}
like image 25
Dávid Pásztor Avatar answered Nov 10 '22 20:11

Dávid Pásztor