10

我正在尝试让我的 Alamofire 管理器实例自动记住并设置 cookie,这是我不成功的尝试:

let cfg = NSURLSessionConfiguration.defaultSessionConfiguration()
let cooks = NSHTTPCookieStorage.sharedHTTPCookieStorage()

// makes no difference whether it's set or left at default
cfg.HTTPCookieStorage = cooks
cfg.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicy.Always

let mgr = Alamofire.Manager(configuration: cfg)

mgr.request(NSURLRequest(URL: NSURL(string: "http://httpbin.org/cookies/set?stack=overflow"))).responseString {
    (_, _, response, _) in
    var resp = response // { "cookies": { "stack": "overflow" } }
    // becomes empty if cfg.HTTPCookieStorage set to nil
}

mgr.request(NSURLRequest(URL: NSURL(string: "http://httpbin.org/cookies"))).responseString {
    (_, _, response, _) in
    var resp = response // { "cookies": {} }
    // always empty no matter what
}

cooks.cookiesForURL(NSURL(string: "http://httpbin.org/cookies")) // 0 elements

第一个 URL 发送一个Set-Cookie : stack=overflow; Path=/标头,然后重定向 (302) 到/cookies(相当于第二个 URL);这在我的浏览器中运行良好(一旦我点击第一个 URL,第二个 URL 总是显示该 cookie)所以我想用 Alamofire 复制这种行为。

4

1 回答 1

19

您的代码一切正常 - 您只是没有考虑到您在执行请求时正在调用异步方法。当执行该代码时,会发生这种情况——每次调用都会mgr.request(...)启动一个新的异步调用,直到上面的所有代码都执行后才会解析:

| configure mgr
|
| request /cookies/set?... ----
|                              \
| request /cookies ----        |
|                      \       |
| cookiesForUrl()      |       |
|                      |       |
| [function returns]   |       |
                       |       |
...time passes...      |       |
                       /       |
  /cookies handler ----        |
                               |
...more time...                |
                               /
  /cookies/set? handler -------

(最后两个处理程序的顺序是不确定的 - 取决于服务器/流量/等。)

因此,您对“ http://httpbin.org/cookies ”的请求实际上并不包含任何 cookie,因为设置 cookie 的请求只是事先发送了一条指令。要查看 cookie,您需要等到第一个调用返回以发送下一个请求。我将东西包装在一个UIViewController子类中:

class CookieViewController: UIViewController {
    // mgr needs to still exist when the response handlers are called
    var mgr: Alamofire.Manager!
    let cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage()

    func configureManager() -> Alamofire.Manager {
        let cfg = NSURLSessionConfiguration.defaultSessionConfiguration()
        cfg.HTTPCookieStorage = cookies
        return Alamofire.Manager(configuration: cfg)
    }

    func setCookies() {
        mgr.request(NSURLRequest(URL: NSURL(string: "http://httpbin.org/cookies/set?stack=overflow")!)).responseString {
            (_, _, response, _) in
            var resp = response // { "cookies": { "stack": "overflow" } }
            println(resp)

            // the cookies are now a part of the URLSession - 
            // we can inspect them and call the next URL
            println(self.cookies.cookiesForURL(NSURL(string: "http://httpbin.org/cookies")!))
            self.checkCookies()
        }
    }

    func checkCookies() {
        mgr.request(NSURLRequest(URL: NSURL(string: "http://httpbin.org/cookies")!)).responseString {
            (_, _, response, _) in
            var resp = response // { "cookies": { "stack": "overflow" } }
            println(resp)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        mgr = configureManager()
        setCookies()
    }
}
于 2014-11-01T15:23:45.373 回答