Get cookies from NSHTTPURLResponse
Asked Answered
L

5

10

I've an extremely weird problem, I'm requesting a URL and I want to get the cookies from it, I've used this way to get the cookies:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response;
    NSDictionary *fields = [HTTPResponse allHeaderFields];
    NSString *cookie = [fields valueForKey:"Set-Cookie"];
}

BUT the cookies is not complete, there is some field is missing, I've checked it on PostMan, all the cookies is there.

I've used also this method when initiating the NSURLRequest.

[request setHTTPShouldHandleCookies:YES];

Where is the problem?

NOTE: This problem is on iOS, I've an android version and it's working fine and all the cookies is there.

Largely answered 28/9, 2013 at 11:46 Comment(6)
Get Charles Proxy (free for a month) and look at exactly what is being sent by the server.Stocks
@Zaph I've tested the server on android application, all the cookies is appear, but in the iOS, there is some of the cookies is missing.Largely
NSHTTPCookieStorage is a possible solution. But there is no substitute to looking at exactly what the server is sending. Perhaps the server is keying on the user agent and sending a different cookie or something else. Charles is easy to use and even works with SSL.Stocks
@Zaph I've tested the service on Charles Proxy, the request have all the cookies that I've supposed to get.Largely
I was getting same problem, solution given by @vn_serg worked greatChura
Did anyone figure out a solution to this? I'm having the same problem.Latchet
L
13

@biloshkurskyi.ss answer is spot on.

I spent half a day trying to find out why some of my cookies were not appearing in my response.allHeaderFields on iOS but it was there on Android (using the same service).

The reason is because some cookies are extracted in advance and stored in the shared cookie store. They will not appear in allHeaderFields.

Here's the swift 3 version of the answer if anyone needs it:

let request = URLRequest(url: myWebServiceUrl)
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: {
    (data, response, error) in
    if let error = error {
        print("ERROR: \(error)")
    } else {
        print("RESPONSE: \(response)")
        if let data = data, let dataString = String(data: data, encoding: .utf8) {
            print("DATA: " + dataString)
        }
        for cookie in HTTPCookieStorage.shared.cookies! {
            print("EXTRACTED COOKIE: \(cookie)") //find your cookie here instead of httpUrlResponse.allHeaderFields
        }
    }
})
task.resume()
Latchet answered 24/10, 2016 at 22:2 Comment(1)
You are a life saver! There are so many questions about this with the wrong answer (using cookiesWithResponseHeaderFields), and you have the correct one. I spent countless hours trying to figure this out. Thank you.Socorrosocotra
O
15

Did you tried following code sample, it should work:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSArray *cookies =[[NSArray alloc]init]; 
    cookies = [NSHTTPCookie 
        cookiesWithResponseHeaderFields:[response allHeaderFields] 
        forURL:[NSURL URLWithString:@""]]; // send to URL, return NSArray
}
Overriding answered 28/9, 2013 at 11:57 Comment(7)
The same, the "Set-Cookie" does not contain all the cookies.Largely
If the server doesn't send the cookie, the client can't have the cookie.His
@His It does send the cookie, but not all the cookies for the iOS, when using the same service on android, it returns all the cookies.Largely
It sounds like you have a server-side problem then.His
This is very useful! As manually pulling out the "Set-Cookie" from "allHeaderFields" results in badly unescaped cookies (which becomes very hard to parse)Vintage
allHeaderFields isn't a function for NSURLResponseMcniel
You need take allHeaderFields from NSHTTPURLResponseMcniel
L
13

@biloshkurskyi.ss answer is spot on.

I spent half a day trying to find out why some of my cookies were not appearing in my response.allHeaderFields on iOS but it was there on Android (using the same service).

The reason is because some cookies are extracted in advance and stored in the shared cookie store. They will not appear in allHeaderFields.

Here's the swift 3 version of the answer if anyone needs it:

let request = URLRequest(url: myWebServiceUrl)
let session = URLSession.shared
let task = session.dataTask(with: request, completionHandler: {
    (data, response, error) in
    if let error = error {
        print("ERROR: \(error)")
    } else {
        print("RESPONSE: \(response)")
        if let data = data, let dataString = String(data: data, encoding: .utf8) {
            print("DATA: " + dataString)
        }
        for cookie in HTTPCookieStorage.shared.cookies! {
            print("EXTRACTED COOKIE: \(cookie)") //find your cookie here instead of httpUrlResponse.allHeaderFields
        }
    }
})
task.resume()
Latchet answered 24/10, 2016 at 22:2 Comment(1)
You are a life saver! There are so many questions about this with the wrong answer (using cookiesWithResponseHeaderFields), and you have the correct one. I spent countless hours trying to figure this out. Thank you.Socorrosocotra
P
10

Try this code:

for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies])
{
    NSLog(@"name: '%@'\n",   [cookie name]);
    NSLog(@"value: '%@'\n",  [cookie value]);
    NSLog(@"domain: '%@'\n", [cookie domain]);
    NSLog(@"path: '%@'\n",   [cookie path]);
}
Plumbum answered 27/11, 2013 at 21:29 Comment(1)
Just a heads up, this wont work on OSX, when the app has sandboxing enabledVintage
S
2
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies])
{
    NSLog(@"name: '%@'\n",   [cookie name]);
    NSLog(@"value: '%@'\n",  [cookie value]);
    NSLog(@"domain: '%@'\n", [cookie domain]);
    NSLog(@"path: '%@'\n",   [cookie path]);
}

Second code is :

NSHTTPURLResponse *HTTPResponsesss = (NSHTTPURLResponse *)response;
NSDictionary *fields = [HTTPResponsesss allHeaderFields];
NSString *cookie = [fields valueForKey:@"Set-Cookie"]; // It is your cookie

NSLog(@"%@", cookie);

Both codes work fine.

Shizue answered 20/3, 2018 at 10:29 Comment(0)
U
0

It will work.

NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
        NSString *cookieValue = @"";
        NSString *cookieHeaderValue = @"";
        NSString *finalCookieValue = @"";
        
        for (NSHTTPCookie *each in cookieStorage.cookies) {
            if ([each.name isEqualToString:@"ASP.NET_SessionId"]) {
                cookieHeaderValue = [cookieHeaderValue stringByAppendingString:each.name];
                cookieHeaderValue = [cookieHeaderValue stringByAppendingString:@"="];
                cookieHeaderValue = [cookieHeaderValue stringByAppendingString:each.value];
                cookieHeaderValue = [cookieHeaderValue stringByAppendingString:@";"];
            } else {
                cookieValue = [cookieValue stringByAppendingString:each.name];
                cookieValue = [cookieValue stringByAppendingString:@"="];
                cookieValue = [cookieValue stringByAppendingString:each.value];
                cookieValue = [cookieValue stringByAppendingString:@";"];
            }
        }
        
        finalCookieValue = [NSString stringWithFormat:@"%@%@", cookieHeaderValue, cookieValue];
Uzia answered 30/10, 2020 at 8:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.