Swift - How to set cookie in NSMutableURLRequest - swift

I'm trying to set cookie in my HTTP request
and I thought that below code would work:
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "GET"
request.setValue("key=value;", forHTTPHeaderField: "Cookie")
but this code is not working.
does anyone have idea how to set it?

Updated answer for Swift 3
You want to look at HTTPCookieStorage.
// First
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)
Original answer for swift 2
You want to look at NSHTTPCookieStorage.
// First
let jar = NSHTTPCookieStorage.sharedHTTPCookieStorage()
let cookieHeaderField = ["Set-Cookie": "key=value"] // Or ["Set-Cookie": "key=value, key2=value2"] for multiple cookies
let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(cookieHeaderField, forURL: url)
jar.setCookies(cookies, forURL: url, mainDocumentURL: url)
// Then
let request = NSMutableURLRequest(URL: url)

Swift 5
if let cookie = HTTPCookie(properties: [
.domain: ".my.domain.name.com",
.path: "/",
.name: "myCookieNameKey",
.value: "K324klj23KLJKH223423CookieValueDSFLJ234",
.secure: "FALSE",
.discard: "TRUE"
]) {
HTTPCookieStorage.shared.setCookie(cookie)
print("Cookie inserted: \(cookie)")
}

This may be useful for some one(Swift 5).
Avoid using NSMutableURLRequest in Swift. Instead follow the below snippet:
func request(with url: URL) -> URLRequest {
var request = URLRequest(url: url)
guard let cookies = HTTPCookieStorage.shared.cookies(for: url) else {
return request
}
request.allHTTPHeaderFields = HTTPCookie.requestHeaderFields(with: cookies)
return request
}

Here is how it works in Swift 3.x after you set cookie using HTTPCookieStorage
let cookies=HTTPCookieStorage.shared.cookies(for: URL(string: cookieURL)!)
let headers=HTTPCookie.requestHeaderFields(with: cookies!)
let request = NSMutableURLRequest(url: requestURL!)
request.allHTTPHeaderFields=headers

Related

Add headers in request but still have a 403

I am trying to request an API in order to get response data. I need to add to headers in the request what I have done using request.addValue(""). It works fine when I am using postman. But I don't why I got no data with Xcode. The response is 403 Forbidden
class Service {
private static let sUrl = URL(string: "https://bff-mobile-dev.XXXXX.com/demands/filter")!
static func getData() {
var request = URLRequest(url: sUrl)
request.httpMethod = "POST"
let session = URLSession(configuration: .default)
request.addValue("Accept-Version", forHTTPHeaderField: "3.0.0")
request.addValue("X-Request-Id", forHTTPHeaderField: "057BC3BD-46E1-4125-9F3B-23805CA3132F")
let task = session.dataTask(with: request) { (data, response, error) in
if let data = data, error == nil {
if let response = response as? HTTPURLResponse {
print(response)
}
}
}
task.resume()
}
}
I believe your key value pair is mixed up when you added the header fields.
request.setValue(value,forHTTPHeaderField: "HeaderFieldName")
Adding like this works.
I think that you inverted values of you header; they should be like this
request.addValue("3.0.0", forHTTPHeaderField: "Accept-Version")
request.addValue("057BC3BD-46E1-4125-9F3B-23805CA3132F", forHTTPHeaderField: "X-Request-Id")
Try something like below
var headerData:[String:String] = [:]
headerData["Accept-Version"] = "3.0.0"
headerData["X-Request-Id"] = "057BC3BD-46E1-4125-9F3B-23805CA3132F"
request.allHTTPHeaderFields = headerData

Set Cookies to HTTP POST Requests from Swift NSURLSession

I'm trying to use the below code but it doesn't work! Any Idea
let jar = NSHTTPCookieStorage.sharedHTTPCookieStorage()
let cookieHeaderField = ["Cookie": self.CookieValue] // var CookieValue = String()
let url = URL
let parameters = ""
let postData:NSData = parameters.dataUsingEncoding(NSASCIIStringEncoding)!
let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(cookieHeaderField, forURL: NSURL(string: url)!)
jar.setCookies(cookies, forURL: NSURL(string: url), mainDocumentURL: NSURL(string: url))
let request = NSMutableURLRequest(URL: NSURL(string: url)!)
request.HTTPMethod = "POST"
request.HTTPBody = postData
let session = NSURLSession.sharedSession()
try this for setting cookies and for better usage understanding.
Below is the swift part for setting up cookie.
let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(response.allHeaderFields as NSDictionary as! [String : String], forURL: response.URL!)
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookies(cookies, forURL: response.URL!, mainDocumentURL: nil)

How to read response cookies using Alamofire

I am trying to read the response cookies for a post request, as done by Postman below
The way I am trying without success right now is
var cfg = NSURLSessionConfiguration.defaultSessionConfiguration()
var cookies = NSHTTPCookieStorage.sharedHTTPCookieStorage()
cfg.HTTPCookieStorage = cookies
cfg.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicy.Always
var mgr = Alamofire.Manager(configuration: cfg)
mgr.request(.POST, "http://example.com/LoginLocalClient", parameters: parameters).responseJSON { response in
print(response.response!.allHeaderFields)
print(NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies)
}
The first print statement contains the 10 header fields without the cookies, the second one contains an empty array.
Any ideas?
You need to extract the cookies from the response using the NSHTTPCookie cookiesWithResponseHeaderFields(_:forURL:) method. Here's a quick example:
func fetchTheCookies() {
let parameters: [String: AnyObject] = [:]
Alamofire.request(.POST, "http://example.com/LoginLocalClient", parameters: parameters).responseJSON { response in
if let
headerFields = response.response?.allHeaderFields as? [String: String],
URL = response.request?.URL
{
let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(headerFields, forURL: URL)
print(cookies)
}
}
}
Swift 5
func fetchTheCookies() {
let parameters: [String: AnyObject] = [:]
Alamofire.request(.POST, "http://example.com/LoginLocalClient", parameters: parameters).responseJSON { response in
if let headerFields = response.response?.allHeaderFields as? [String: String], let URL = response.request?.url
{
let cookies = HTTPCookie.cookies(withResponseHeaderFields: headerFields, for: URL)
print(cookies)
}
}
}
All the configuration customization you are attempting to do won't have any affect. The values you have set are already all the defaults.
Please be advised that the accepted answer does not work if the cookies are not posted within the header response. Apparently, some cookies are extracted in advance and stored in the shared cookie store and will not appear with the response.
You must use HTTPCookieStorage.shared.cookies instead.
Swift 3:
Alamofire.request(url, method: HTTPMethod.post, parameters: parameters).responseData { (responseObject) -> Void in
if let responseStatus = responseObject.response?.statusCode {
if responseStatus != 200 {
// error
} else {
// view all cookies
print(HTTPCookieStorage.shared.cookies!)
}
}
}
Credit goes to Travis M.
If you just want to read all the cookies against the domain you are interacting with, you can get all cookies with this method.
let cookies = Alamofire.Manager.sharedInstance.session.configuration.HTTPCookieStorage?.cookiesForURL(NSURL(string: "mydomain.com")! )
It returns an optional array of NSHTTPCookie items. (Swift 2.2 and Alamofire 3.4)
Swift 4.1:
let cookies = Alamofire.SessionManager.default.session.configuration.httpCookieStorage?.cookies(for: url)
the above code was correct I have used in this way -
var allCookies: [NSHTTPCookie]?
if let headerFields = aResponse.response?.allHeaderFields as? [String: String],
URL = aResponse.request?.URL {
allCookies = NSHTTPCookie.cookiesWithResponseHeaderFields(headerFields, forURL: URL)
for cookie in allCookies! {
print(cookie)
let name = cookie.name
if name == "nmSession" {
let value = cookie.value
print(value)
}
}
}
#lespommes
This is the only way I have received cookies. Now I can finally see Set-Cookie in a response:
let parameters = ["postLogin": ["login": "mymail#gmail.com", "password": "myPassword"]]
let url = NSURL(string: "your-website-with-cookies.com")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(parameters, options: [])
Alamofire.request(request)
.responseJSON { response in
debugPrint(response)
if response.result.isSuccess {
...
}
}else if (response.result.isFailure){
...
}
}

HTTP POST request in Swift

How do I post the request on iOS? Actually when I logged into Facebook it fetches the user informations like username, from where there are login (latitude, longitude). Is it possible to use api
Link: http://buddysin.aumkiiyo.com/fbc
My code is:
#IBAction func btnAPI(sender: UIButton)
{
//startConnection()
connectToWebAPI()
}
func connectToWebAPI()
{
//setting up the base64-encoded credentials
let id = "1620912344817986"
//let password = "pass"
let loginString = NSString(format: "%#:%#", id)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(nil)
//creating the requestz
let url = NSURL(string: "http://buddysin.aumkiiyo.com/fbc")
var request = NSMutableURLRequest(URL: url!)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession.sharedSession()
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let urlConnection = NSURLConnection(request: request, delegate: self)
request.HTTPMethod = "POST"
request.setValue(base64LoginString, forHTTPHeaderField: "Authorization")
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
if (error != nil) {
println(error)
}
else {
// converting the data into Dictionary
var error: NSError?
let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as! NSDictionary
println(jsonResult)
}
})
//fire off the request
task.resume()
}
while I run, the fatal error where displayed as
`fatal error: unexpectedly found nil while unwrapping an Optional value`
in the "jsonResult"
i think it is better to use Alomafire. As AFNetWorking in Objective-C it is a library which simplified a lot http request.
Visit this question to check for my post-request function (if
you don't want to use Alamofire for any reasons)
Visit this question to check for steps you need to do if you
want to add Alamofire to your XCode-project
If you need to get json-data from your server, use
SwiftyJSON. It's as simple as dragging SwiftyJSON.swift into
your project with checking "Copy items if needed" and using like
let jsonData = JSON(data: yourDataFromServer)
Also you can view this question to check out for steps to encode
json-post data to send it to server.
Hope I helped :)
You should find which varible due to this error:
for example data,
if let dataTemp = data as? NSDictionary {
}
FYI:
Here is a way of 'POST' method of AFNetworking in swift, below code should be in your connectToWebAPI method, wrap your url ready into NSURL.
let manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: yourURL))
manager.POST("path", parameters: ["key":value], success: { (opeartion:AFHTTPRequestOperation!, data:AnyObject!) -> Void in
},failure: { (operation:AFHTTPRequestOperation!, error:NSError!) -> Void in
})
Tutorial to install AFNetworking.
https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking
It is quite easy to do with Alamofire
func postSomething(completionHandler: #escaping CompletionHandler){
let loginString = NSString(format: "%#:%#", id)
let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = loginData.base64EncodedStringWithOptions(nil)
let headers: HTTPHeaders = [
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "base64LoginString",
]
let parameters: Parameters = [
"parameter": value,
"parameter2": value2
]
Alamofire.request("http://buddysin.aumkiiyo.com/fbc", method: .post, parameters: parameters, encoding: URLEncoding.default, headers: SFAppServicesManager.sharedInstance.genericHeader()).responseJSON { response in
if let JSON = response.result.value {
let userDictionary = JSON as! NSDictionary
completionHandler(true)
} else {
completionHandler(false)
}
}
}

Submit Decimal/Float in URL Request with Swift

How can a value such as "1.5" be passed in a a URL POST request using swift?
For example:
let number = "1.5"
let numberValue = number.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let server:String = "www.someserver.com"
let phpFile:String = "/php/SomePHPScript.php"
let baseURL = NSURL(string: "http://\(server)\(phpFile)")
let url = NSURL(string: "?value=\(numberValue)", relativeToURL: baseURL)
let cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
var request = NSMutableURLRequest(URL: url!, cachePolicy: cachePolicy, timeoutInterval: 10.0)
request.HTTPMethod = "POST"
var dataString = ""
let requestBodyData = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
request.HTTPBody = requestBodyData
// etc...
This compiles fine but crashes on execution. It seems converting this to JSON would fix it, but is there cleaner way?
EDIT
stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) returns optional. It needed to be unwrapped.
stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) returns optional. It needed to be unwrapped.