Cook ie неправильно выставлен в Swift запросе - PullRequest
0 голосов
/ 17 июня 2020

У нас есть сервер Node.js express, скажем, на domain.xyz. Со стороны iOS мы хотим сделать два запроса к двум разным конечным точкам:

  1. domain.xyz/api/first -> Получить Set-Cookie из этого запроса и передать его в запросе Cookie из следующего
  2. domain.xyz/api/second

Используя curl, он отлично работает:

# First request
curl -v -H 'Content-type: application/json' --data '{
  "My": "Data"
}' http://domain.xyz/api/first?ios_key=123
...
< Set-Cookie: connect.sid=2346283746....
...

# Second request passing exactly the content of the Set-Cookie response header from the previous request
curl -v -H "Cookie: connect.sid=2346283746...." http://domain.xyz/api/second?ios_key=123

Цель состоит в том, чтобы запустить те же запросы из iOS приложение, использующее Swift. Мы пробовали:

let jsonData = try? JSONSerialization.data(withJSONObject: json)

    // create post request
    let url = URL(string: "https://domain.xyz/api/first?ios_key=123")!
    let jar = HTTPCookieStorage.shared
    let cookieHeaderField = ["Set-Cookie": "key=value"] // Or ["Set-Cookie": "key=value, key2=value2"] for multiple cookies
    let cookies = HTTPCookie.cookies(withResponseHeaderFields: cookieHeaderField, for: url)
    jar.setCookies(cookies, for: url, mainDocumentURL: url)

    // Then
    var request = URLRequest(url: url)

    request.httpMethod = "POST"

    // insert json data to the request
    request.httpBody = jsonData



    let task = URLSession.shared.dataTask(with: request) { data, response, error in

        if let httpResponse = response as? HTTPURLResponse {
             if let cookiesRes = httpResponse.allHeaderFields["Set-Cookie"] as? String {

                guard let data = data, error == nil else {
                    print(error?.localizedDescription ?? "No data")
                    return
                }
                    let d = String(data: data, encoding: String.Encoding.utf8)
                print(response)

                let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
                if let responseJSON = responseJSON as? [String: Any] {

                    // The cookiesRes variable seems to be fine at this point
                    self.getOrderRequest(cookies: cookies, cookiesResponse: cookiesRes)
                }

             }
        }

    }

    task.resume()
}

После получения Set-Cookie из ответа мы передаем его в следующую функцию через cookiesRes (аргумент cookiesResponse):

func getOrderRequest(cookies: [HTTPCookie], cookiesResponse: String)  {

    let url = URL(string: "https://domain.xyz/api/second?ios_key=123")!
    var request = URLRequest(url: url)
    request.httpMethod = "GET"

    // Here we need to set the cookies
    request.setValue(cookiesResponse, forHTTPHeaderField: "Cookie")
    request.httpShouldHandleCookies = true

    // Then
    print(request.allHTTPHeaderFields)

    let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error -> Void in
        print(response!)

        let d = String(data: data!, encoding: String.Encoding.utf8)
            print(d)

        do {
            let json = try JSONSerialization.jsonObject(with: data!) as! Dictionary<String, AnyObject>
            print(json)
        } catch {
            print(error.localizedDescription)
        }
    })

    task.resume()
}

Однако заголовок Cookie установлен неправильно, потому что новый сеанс создается Express.

Как я могу точно воспроизвести точные запросы curl, которые работают в Swift: установка Cook ie заголовок во втором запросе?

...