У нас есть сервер Node.js express, скажем, на domain.xyz
. Со стороны iOS мы хотим сделать два запроса к двум разным конечным точкам:
domain.xyz/api/first
-> Получить Set-Cookie
из этого запроса и передать его в запросе Cookie
из следующего 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 заголовок во втором запросе?