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
Map Object into 2D Array Swift for Tableview Sections
Detect Permission of Media Library iOS
Uibutton Target Action Inside Uiview
How to Change Select Box Background Without Losing The Right Arrow on Mobile Safari
Prepareforsegue Not Called from Custom UItableviewcell
Viewdiddisappear Not Called When Use Presentviewcontroller
Uipageviewcontroller Setviewcontrollers, UIpagecontrol Not Showing Right Current Number
Exceeding Max Text("") Concatenation Length - Swiftui -
Go Back to View Controller from Skscene
Spritekit Not Respecting Zposition
Core Data - Fetch All Entities Using the Same Field
How to Keep Animated Gifs Animated While Scrolling on iOS Devices
App Crashes After Updating Coredata Model That Is Being Displayed in a UItableview
How to Get Nsnumberformatter Currency Style from Isocurrencycodes
Apns Http2 API Not Returning Status 410 After Uninstalling App