Mikara
Mikara

Reputation: 143

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

Upvotes: 14

Views: 18437

Answers (2)

Xavier L.
Xavier L.

Reputation: 747

Here is the Problem:

Your member=John is what people generally refer to as a "URL query parameter". In general, URL requests have query parameters as a part of the URL string itself and not the request's httpbody.


Quick and Dirty Solution:

Simply removing

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

and passing the whole "www.somelink.com/stuff/searchmembers?member=John" into your getAllMembers(urlString:) function should do the trick.


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 "www.somelink.com/stuff/searchmembers" into this function's first parameter, urlString.

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

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

which works as one would expect.

Upvotes: 19

David Pasztor
David Pasztor

Reputation: 54716

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

Upvotes: 5

Related Questions