Search code examples
swifturlsessionhttpcookie

How to get cookies from URLSession response in Swift


This is my first time for asking.

I’m using Swift 5. I'm making a log-in feature, so I need to save "JSESSIONID" using Cookie, so I'm trying to read data from response header's Set-Cookie parameter, but I can't get any data. How can I get data?

I checked "Set-Cookie" is sent by servlet using curl command. I attached a response header.

jun-MacBook-Pro:~ junki-t$ curl -X POST -D - -d "SOME PARAMETERS" http://example.com/PATH/UserProfilingService
HTTP/1.1 302 Found
Date: Tue, 23 Jul 2019 10:49:02 GMT
Set-Cookie: JSESSIONID=91********************BA; Path=/******; HttpOnly
Location: /?AUTHORIZED=yes&USERPROFILEKEY=*********
Content-Length: 0
Connection: close
Content-Type: text/plain

jun-MacBook-Pro:~ junki-t$ 

I tried to dump the response data in Swift application, but "Set-Cookie" does not found.

- some: <NSHTTPURLResponse: 0x281050860> { URL: http://example.com/?AUTHORIZED=yes&USERPROFILEKEY=********* } { Status Code: 200, Headers {
    "Accept-Ranges" =     (
        bytes
    );
    Connection =     (
        close
    );
    "Content-Length" =     (
        146
    );
    "Content-Type" =     (
        "text/html"
    );
    Date =     (
        "Wed, 17 Jul 2019 08:51:38 GMT"
    );
    Etag =     (
        "\"92-5********a3\""
    );
    "Last-Modified" =     (
        "Wed, 30 Nov 2016 07:44:17 GMT"
    );
    Server =     (
        Apache
    );
} } #0
    - super: NSURLResponse
      - super: NSObject
func tryAuth() {
    let id = "*****"
    let pass = "*****"

    let url = URL(string: "<Some url>")
    var url_request = URLRequest(url: url!)
    url_request.httpMethod = "POST"
    url_request.httpShouldHandleCookies = true

    let body = "SOME PARAMETERS FOR AUTHENTICATE"
    url_request.httpBody = body.data(using: String.Encoding.utf8)

    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
    session.configuration.httpCookieAcceptPolicy = .always
    session.configuration.httpCookieStorage = HTTPCookieStorage.shared
    session.configuration.httpShouldSetCookies = true

    session.dataTask(with: url_request).resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
    let httpResponse = response as? HTTPURLResponse
    var dict = httpResponse?.allHeaderFields
    let cookies = HTTPCookie.cookies(withResponseHeaderFields: httpResponse?.allHeaderFields as! [String : String], for: response.url!)
    dump(cookies) // for testing.
    //
    // some process to get/save cookie.
    //
}

I think cookies have some data(I want to get "JSESSIONID"), but cookies have 0 elements.

So I can't get any cookie data.


Solution

  • From HTTPCookieAcceptPolicy documentation:

    This property determines the cookie accept policy for all tasks within sessions based on this configuration. The default value is NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain. You can change it to any of the constants defined in the NSHTTPCookieAcceptPolicy enumerated type. If you want more direct control over what cookies are accepted, set this value to NSHTTPCookieAcceptPolicyNever and then use the allHeaderFields and cookiesWithResponseHeaderFields:forURL: methods to extract cookies from the URL response object yourself.

    So, you need to set session.configuration.httpCookieAcceptPolicy = .never or you can use HTTPCookieStorage.shared.cookies(for: response.url) if you want the system to set cookies automatically.