swifturlnsurlsession

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

Solution

  • 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.