How to Make a Nsurlsesssion Get Request with Cookies

How to make a NSURLSesssion GET request with cookies

The other answers may work generally, but specifically for me this is how I coded the request in order to get a response from Pinterest's server. Note that specifically what I am doing I think is related to a possible bug in Pinterest's server, see: https://github.com/pinterest/ios-pdk/issues/124

I commented out my personal Pinterest session ID

var cookieSession = String()
var cookieCSRFToken = String()

var myWebServiceUrl = URL(string: "https://www.pinterest.com/r/pin/186195765821344905/4801566892554728205/a9bb098fcbd6b73c4f38a127caca17491dafc57135e9bbf6a0fdd61eab4ba885")

let requestOne = URLRequest(url: myWebServiceUrl!)
let sessionOne = URLSession.shared

let taskOne = sessionOne.dataTask(with: requestOne, 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)
} // end: if

var cookies:[HTTPCookie] = HTTPCookieStorage.shared.cookies! as [HTTPCookie]
print("Cookies Count = \(cookies.count)")
for cookie:HTTPCookie in cookies as [HTTPCookie] {

// Get the _pinterest_sess ID
if cookie.name as String == "_pinterest_sess" {
//var cookieValue : String = "CookieName=" + cookie.value as String
cookieSession = cookie.value as String
print(cookieSession)
}

// Get the csrftoken
if cookie.name as String == "csrftoken" {
cookieCSRFToken = cookie.value
print(cookieCSRFToken)
}
} // end: for

} // end: if
})
taskOne.resume()

var requestTwo = URLRequest(url: myWebServiceUrl!)

cookieSession = "XXXXXXXX"

cookieCSRFToken = "JHDylCCKKNToE4VXgofq1ad3hg06uKKl"

var cookieRequest = "_auth=1; _b=\"AR4XTkMmqo9JKradOZyuMoSWcMdsBMuBHHIM21wj2RPInwdkbl2yuy56yQR4iqxJ+N4=\"; _pinterest_pfob=disabled; _pinterest_sess=\"" + cookieSession + "\"; csrftoken=" + cookieCSRFToken as String

requestTwo.setValue(cookieRequest as String, forHTTPHeaderField: "Cookie")

let taskTwo = sessionOne.dataTask(with: requestTwo, completionHandler: { (data, response, error) in
if let error = error {
print("ERROR: \(error)")
}
else {
print("RESPONSE: \(response)")

} // end: if
})
taskTwo.resume()

PlaygroundPage.current.needsIndefiniteExecution = true

How to get cookie from a NSURLSession with Swift?

The Swift rendition might look something like:

let task = session.dataTask(with: request) { data, response, error in
guard
let url = response?.url,
let httpResponse = response as? HTTPURLResponse,
let fields = httpResponse.allHeaderFields as? [String: String]
else { return }

let cookies = HTTPCookie.cookies(withResponseHeaderFields: fields, for: url)
HTTPCookieStorage.shared.setCookies(cookies, for: url, mainDocumentURL: nil)
for cookie in cookies {
var cookieProperties = [HTTPCookiePropertyKey: Any]()
cookieProperties[.name] = cookie.name
cookieProperties[.value] = cookie.value
cookieProperties[.domain] = cookie.domain
cookieProperties[.path] = cookie.path
cookieProperties[.version] = cookie.version
cookieProperties[.expires] = Date().addingTimeInterval(31536000)

let newCookie = HTTPCookie(properties: cookieProperties)
HTTPCookieStorage.shared.setCookie(newCookie!)

print("name: \(cookie.name) value: \(cookie.value)")
}
}
task.resume()

How to POST with cookies by NSURLSession

Unless you're customizing the NSURLSession instance via NSURLSessionConfiguration, you should just be able to set the cookie via the shared NSHTTPCookieStorage using the setCookie selector.

Set cookies with NSURLSession

You can probably get away with just using the sharedHTTPCookieStorage for NSHTTPCookieStorage, and then use setCookies:forURL:mainDocumentURL: or the single setCookie: - the latter might be better for your needs.

If this doesn't work you might need to setup the NSURLSessionConfiguration and set the NSHTTPCookieStorage

The docs don't state it, but the defaultSessionConfiguration might use the shared store anyway.

NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;

NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:[response URL]];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:cookies forURL:[response URL] mainDocumentURL:nil];

NSLog(@"sttaus code %i", httpResp.statusCode);
if (error) {
[self.delegate signinWithError:error];
}
else {
[self.delegate signinWithJson:data];
}
}] resume];

How do I retrieve a cookie from a NSURLResponse in Swift?

// Setup a NSMutableURLRequest to your desired URL to call along with a "POST" HTTP Method

var aRequest = NSMutableURLRequest(URL: NSURL(string: "YOUR URL GOES HERE")!)
var aSession = NSURLSession.sharedSession()
aRequest.HTTPMethod = "POST"

// Pass your username and password as parameters in your HTTP Request's Body

var params = ["username" : "ENTER YOUR USERNAME" , "password" : "ENTER YOUR PASSWORD"] as Dictionary <String, String>
var err: NSError?
aRequest.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)

// The following header fields are added so as to get a JSON response

aRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
aRequest.addValue("application/json", forHTTPHeaderField: "Accept")

// Setup a session task which sends the above request

var task = aSession.dataTaskWithRequest(aRequest, completionHandler: {data, response, error -> Void in

// Save the incoming HTTP Response

var httpResponse: NSHTTPURLResponse = response as! NSHTTPURLResponse

// Since the incoming cookies will be stored in one of the header fields in the HTTP Response, parse through the header fields to find the cookie field and save the data

let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(httpResponse.allHeaderFields, forURL: response.URL!) as! [NSHTTPCookie]

NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookies(cookies as [AnyObject], forURL: response.URL!, mainDocumentURL: nil)

})

task.resume()

Swift NSURLSession NSURLRequest Cookies are not accepted

Issue is solved

In fact, cookies are accepted with the above code. I tried logging in to a different site and it worked. Also the login persisted. So why it did not work with my carrier's website?

Stupid me, my carrier has CSRF protection and other hidden form fields which I did not pay attention to. Hence, login did not work. Now I know how to fix it.

For anyone interested, I'll post my updated HttpClient.swift file which is a bit more tidy, I hope.

Please feel free to comment on my code and give me hints for improvement.

import Foundation

public class HttpClient {

private var session: NSURLSession
private var request: NSMutableURLRequest

public init(url: String) {
self.session = NSURLSession.sharedSession()
session.configuration.HTTPShouldSetCookies = true
session.configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicy.OnlyFromMainDocumentDomain
session.configuration.HTTPCookieStorage?.cookieAcceptPolicy = NSHTTPCookieAcceptPolicy.OnlyFromMainDocumentDomain
self.request = NSMutableURLRequest(URL: NSURL(string: url)!)
}

public func send() -> String {
var ready = false
var content: String!

var task = session.dataTaskWithRequest(self.request) {
(data, response, error) -> Void in
content = NSString(data: data, encoding: NSASCIIStringEncoding) as! String
ready = true
}
task.resume()
while !ready {
usleep(10)
}
if content != nil {
return content
} else {
return ""
}
}

public func setUrl(url: String) -> HttpClient {
self.request.URL = NSURL(string: url)
return self
}

public func getMethod() -> String {
return self.request.HTTPMethod
}

public func setMethod(method: String) -> HttpClient {
self.request.HTTPMethod = method
return self
}

public func addFormData(data: Dictionary<String, String>) -> HttpClient {
var params: String = ""
var ctHeader: String? = self.request.valueForHTTPHeaderField("Content-Type")
let ctForm: String = "application/x-www-form-urlencoded"

if(data.count > 0) {
for(name, value) in data {
params += name + "=" + value + "&"
}

params = params.substringToIndex(params.endIndex.predecessor())
self.request.HTTPBody = params.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)

if ctHeader != nil {
self.request.setValue(ctForm, forHTTPHeaderField: "Content-Type")
}
}

return self
}

public func removeFormData() -> HttpClient {
self.request.setValue("text/html", forHTTPHeaderField: "Content-Type")
self.request.HTTPBody = "".dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)

return self
}
}

How to get cookies from URLSession response in Swift

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.



Related Topics



Leave a reply



Submit