Authorization Header not setting in Alamofire 5? - ios

I am setting the basic auth token to my URLRequest and using Alamofire to execute.
I set 3 headers, content, accept and auth...content and accept are visible in the network traffic but auth is not. It is available if i print the headers of the URLRequest before its sent...
Any ideas here? as i dont see how its removing the auth header before posting
Code as follows:
// Construct url
let url = try APIConstants.baseUrl.asURL()
// Append path
var urlRequest = URLRequest(url: url.appendingPathComponent(path))
// Determine HTTP method
urlRequest.httpMethod = method.rawValue
let headers: HTTPHeaders = [
.contentType(APIConstants.ContentType.json.rawValue),
.accept(APIConstants.ContentType.json.rawValue),
]
if let token = token {
urlRequest.addValue("\(APIConstants.API.token.rawValue) \(token.key)",
forHTTPHeaderField: "Authorization")
}
urlRequest.headers = headers
// Add http body to request
if let parameters = parameters {
do {
let data = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
urlRequest.httpBody = data
} catch (_) {
print("APIRouter: Failed to parse body into request.")
}
}
//Encoding
let encoding: ParameterEncoding = {
switch method {
case .get:
return URLEncoding.default
default:
return JSONEncoding.default
}
}()
return try encoding.encode(urlRequest, with: parameters)
}
In my rest client i execute like this:
return Observable<T>.create { observer in
let request = AF.request(urlConvertible).responseDecodable { (response: DataResponse<T, AFError>) in
switch response.result {
case .success(let value):
observer.onNext(value)
observer.onCompleted()
case .failure(let error):
switch response.response?.statusCode {
case 403:
observer.onError(APIError.forbidden)
case 404:
observer.onError(APIError.notFound)
case 409:
observer.onError(APIError.conflict)
case 500:
observer.onError(APIError.internalServerError)
default:
observer.onError(error)
}
}
}
return Disposables.create {
request.cancel()
}
}
}
Edit:
Updated func to show further issue:
func asURLRequest() throws -> URLRequest {
// Construct url
let url = try APIConstants.baseUrl.asURL()
// Append path
var urlRequest = URLRequest(url: url.appendingPathComponent(path))
// Determine HTTP method
urlRequest.httpMethod = method.rawValue
let headers: HTTPHeaders = [
.contentType(APIConstants.ContentType.json.rawValue),
.accept(APIConstants.ContentType.json.rawValue),
.authorization("Token a5555485aa251b28fdsfasdfdsb379c131fddad")
]
urlRequest.headers = headers
// Add http body to request
if let parameters = parameters {
do {
let data = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
urlRequest.httpBody = data
} catch (_) {
print("APIRouter: Failed to parse body into request.")
}
}
//Encoding
let encoding: ParameterEncoding = {
switch method {
case .get:
return URLEncoding.default
default:
return JSONEncoding.default
}
}()
return try encoding.encode(urlRequest, with: parameters)
}

After setting the Authorization header in your URLRequest:
urlRequest.addValue("\(APIConstants.API.token.rawValue) \(token.key)", forHTTPHeaderField: "Authorization")
then you override all the request's headers by setting headers property:
urlRequest.headers = headers
A nice solution would be to update the headers that you already created above, like this:
var headers: HTTPHeaders = [
.contentType(APIConstants.ContentType.json.rawValue),
.accept(APIConstants.ContentType.json.rawValue),
]
if let token = token {
headers.add(.authorization("\(APIConstants.API.token.rawValue) \(token.key)"))
}
urlRequest.headers = headers

Another solution is to use KeyValue pair as follows:
var header: HTTPHeaders = [:]
if let token = getValueFromUserDefaults(keyName: "authToken") as? String {
header["Authorization"] = token
}
I always use this method. It's more handy for me.

Related

Alamofire - add both query parameter and body

I am trying to send a request that should contain both URL parameters and request body in JSON. Backend doesn't recognize the request and returns 400 status code.
This is how I tried to solve the problem
enum MyRequestsRouter: URLRequestConvertible {
case RequestA(paramA: String, bodyInJsonString: String),
RequestB(paramB: String)
var baseURL: URL {
URL(string: "http://127.0.0.1:8080")!
}
var method: HTTPMethod {
switch self {
case .RequestA: return .post
case .RequestB: return .get
}
}
var path: String {
switch self {
case .RequestA: return "/api/a"
case .RequestB: return "/api/b"
}
}
var parameters: Parameters? {
switch self {
case .RequestA(let paramA, let bodyInJsonString):
return [
"paramA": paramA
]
case .RequestB(let paramB):
return ["paramB": paramB]
default:
return nil
}
}
func asURLRequest() throws -> URLRequest {
let url = baseURL.appendingPathComponent(path)
var request = URLRequest(url: url)
request.method = method
switch self {
case let .RequestA(paramA, bodyInJsonString):
// here I am specifying `paramA` value
request = try URLEncoding.default.encode(request, with: parameters)
// here body is already serialized to Json
request.httpBody = Data(bodyInJsonString.utf8)
request.setValue("application/json", "Content-Type")
case let .RequestB(paramB):
request = try URLEncoding.default.encode(request, with: parameters)
}
return request
}
}
And this is how I am making API call
let json: Data = try JSONEncoder().encode(notSerializedBodyObject)
let jsonString = String(data: json, encoding: .utf8)
AF.request(MyRequestsRouter.RequestA(paramA: "paramA", bodyInJsonString: jsonString!)).response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.error)")
// etc
}
}
As you can see the request URL is supposed to be
http://127.0.0.1:8080/api/a?paramA=paramA plus request body in JSON. But response is 400 Bad request.
How to properly configure Alomofire?
Alamofire's URLEncoding has an initializer that gets destination as parameter. Based on documentation:
Destination defining where the encoded query string will be applied.
.methodDependent by default.
By default .methodDependent case checks the HTTP method of the request and only on .get, .head and .delete requests it encodes the passed parameters in the URL.
Given that fact, you never see paramA in your request (not even in the body) because you override it in the following line:
// here body is already serialized to Json
request.httpBody = Data(bodyInJsonString.utf8)
So, instead of using the default URLEncoding, you can simply call URLEncoding's initializer directly passing as destination the .queryString case like this:
// here I am specifying `paramA` value
request = try URLEncoding(destination: .queryString).encode(request, with: parameters)
// here body is already serialized to Json
request.httpBody = Data(bodyInJsonString.utf8)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
That way you will have a request with paramA in the URL and your JSON as a body.

iOS Swift Http request post method using header x-www-form-urlencoded?

I have to make an API call with headers as application/x-www-form-urlencoded value as a JSON string. When give parameter value and header in postman, it works fine and returns status code 200 ok. Here i am using backend node js . Post method does not work in front end. Dont know what is the issue.
Errors:
Sometimes i am getting request time out,
NSUrlfailingstring, finished with status code 1001
Here is the code of my backend :
var status = {
SUCCESS : 'success',
FAILURE : 'failure'
}
var httpStatus = {
OK : HttpStatus.OK,
ISE : HttpStatus.INTERNAL_SERVER_ERROR,
BR : HttpStatus.BAD_REQUEST
}
exports.likes= function(req, res){
var Username =req.body.username;
var likecount=req.body.count;
var likedby = req.body.likedby;
var postId = req.body.postId;
var tokenId = req.body.tokenId;
var message = {
to: tokenId,
collapse_key: '',
data: {
name:Username,
Message:"Content about message",
Redirect:"TopostId : "+postId,
time: ""
},
notification: {
title: "Hey Buddy , Someone have liked your post",
body: likedby +"Likedyourpost",
icon: "notification"
}
};
fcm.send(message)
.then(function (response) {
console.log("Successfully sent with response: ", response);
res.status(httpStatus.OK).json({
status: status.SUCCESS,
code: httpStatus.OK,
error:''
});
return;
})
.catch(function (err) {
console.log(err);
});
};
module.exports = function(app) {
app.post('/likesnotification', notification.likes);
app.post('/commentsnotification', notification.comments);
app.post('/othernotification', notification.othernot);
app.post('/followrequset', notification.followreq);
app.post('/followresponse', notification.followres);
app.post('/publicaccountfollow', notification.publicacfollow);
};
Here is my front code in ios Swift:
Try 1:
func postNotification(postItem: String, post: Post) {
print("Get token from post:::",post.token)
print(postItem)
let token = UserDefaults.standard.string(forKey: "token")
let headers: HTTPHeaders = ["Content-Type" :"application/x-www-form-urlencoded"]
let parameters : [String:Any] = ["count":post.likeCount!, "likedby":currentName, "postId=":postItem, "token": post.token!]
Alamofire.request("http://highavenue.co:9000/likesnotification/", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if let data = response.result.value{
print(data)
}
break
case .failure(_):
print(response.result.error as Any)
break
}
}
}
Try 2:
var parameters = [String:Any]()
parameters["count"] = post.likeCount!
parameters["likedby"] = currentName
parameters["postId"] = postItem
parameters["token"] = post.token!
let Url = String(format: "http://highavenue.co:9000/likesnotification")
guard let serviceUrl = URL(string: Url) else { return }
// let loginParams = String(format: LOGIN_PARAMETERS1, "test", "Hi World")
let parameterDictionary = parameters
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
return
}
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options:
[])
print(json)
}catch {
print(error)
}
}
}.resume()
Any help much appreciated pls.
I seen your code you are suppose to call the header parameter which was you create for it. You are not pass header in alamofire request method.
Like below :
let headers: HTTPHeaders = ["Content-Type" :"application/x-www-form-urlencoded"]
let parameters : [String:Any] = ["count":post.likeCount!, "likedby":currentName, "postId=":postItem, "token": post.token!]
Alamofire.request("http://highavenue.co:9000/likesnotification/", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { (response:DataResponse<Any>) in
switch(response.result) {
case .success(_):
if let data = response.result.value{
print(data)
}
break
case .failure(_):
print(response.result.error as Any)
break
}
}
}

Request time out error 1001 using alamofire in ios swift?

Here i am sending parameter value like username, user toke, post id, etc to backend using alamofire. if status success then, notification will will send from backend. Inside postnotification function i have tried post method code using alamofire and datatask method but it does not work. In console i am getting request time out or nothing.
Here is my code :
func postNotification(postItem: String, post: Post) {
// declare parameter as a dictionary which contains string as key and value combination. considering inputs are valid
print("Get token from post:::",post.token)
print(postItem)
let token = UserDefaults.standard.string(forKey: "token")
//create the url with URL
var parameters = [String:Any]()
parameters["count"] = post.likeCount!
parameters["likedby"] = currentName
parameters["postId"] = postItem
parameters["token"] = post.token!
let Url = String(format: "http://highavenue.co:9000/likesnotification")
guard let serviceUrl = URL(string: Url) else { return }
// let loginParams = String(format: LOGIN_PARAMETERS1, "test", "Hi World")
let parameterDictionary = ["username" : "Test", "password" : "123456"]
var request = URLRequest(url: serviceUrl)
request.httpMethod = "POST"
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONSerialization.data(withJSONObject: parameters, options: []) else {
return
}
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
}catch {
print(error)
}
}
}.resume()
// let headers: HTTPHeaders = ["Content-Type" :"application/x-www-form-urlencoded"]
//
// Alamofire.request("http://highavenue.co:9000/likesnotification", method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
// // original URL request
// print("Request is :",response.request!)
//
// // HTTP URL response --> header and status code
// print("Response received is :",response.response)
//
// // server data : example 267 bytes
// print("Response data is :",response.data)
//
// // result of response serialization : SUCCESS / FAILURE
// print("Response result is :",response.result)
//
// debugPrint("Debug Print :", response)
//
//
// }
// Alamofire.request("http://highavenue.co:9000/likesnotification", method: HTTPMethod.post, parameters: json, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
//
// // original URL request
// print("Request is :",response.request!)
//
// // HTTP URL response --> header and status code
// print("Response received is :",response.response)
//
// // server data : example 267 bytes
// print("Response data is :",response.data)
//
// // result of response serialization : SUCCESS / FAILURE
// print("Response result is :",response.result)
//
// debugPrint("Debug Print :", response)
// }
}
Any help much appreciated pls..
Yaah solved it. There was a negligence mistake. I used an additional slash in the URL. I changed the web API to a different folder and I made this mistake while changing it in the iOS code. and Also Set your timeout interval here.
let RequestData = NSMutableURLRequest(URL: NSURL.init(string: "Your URL Hear")!)
RequestData.HTTPMethod = "POST"
RequestData.timeoutInterval = 250 // Time interval here.
Alamofire.request(RequestData).responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) { // response
print(responseData.result.value!)
}
}
Hope this Help You..

Can't get correct api call in swift 3

I tried this particular API in postman, and it returns a fine result.
Thus, i created a parameter
["JsonRequest": "{\"header\":\"GetLocationListReq\",\"accessKey\":\"fakeKey\"}"]
but when i pass this parameter when calling this API using swift and alamofire in my Xcode project, i always get back an error.
For those who are interested, my apiRouter is
//
// WINAPIRouter.swift
// Winner21
//
// Created by Lin Hairui on 27/4/17.
// Copyright © 2017 Pioneers & Leaders (Publishers). All rights reserved.
//
import Foundation
import Alamofire
enum WINAPIRouter : URLRequestConvertible {
static let baseURL = Constant.baseURL
case get(String)
case create([String:Any],String?)
case delete(String)
func asURLRequest() throws -> URLRequest {
var method : HTTPMethod {
switch self {
case .get:
return HTTPMethod.get
case .create:
return HTTPMethod.post
case .delete:
return HTTPMethod.delete
}
}
let params:(Dictionary<String, Any>?) = {
switch self {
case .get, .delete:
return nil
case .create(let params, _):
var fieldParams = params
fieldParams["accessKey"] = Constant.kAPIAccessKey
let jsonData: NSData
do {
jsonData = try JSONSerialization.data(withJSONObject: fieldParams, options: JSONSerialization.WritingOptions()) as NSData
let jsonString = NSString(data: jsonData as Data, encoding: String.Encoding.utf8.rawValue) as! String
let authParam : [String : Any] = [
"JsonRequest" : jsonString
]
print("google was here \(authParam)")
return authParam
} catch _ {
print ("JSON Failure")
}
return nil
}
}()
let url : URL = {
return URL(string: Constant.baseURL)!
}()
var urlRequest = URLRequest(url: url)
// urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
// urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
urlRequest.httpMethod = method.rawValue
print("facebook was here = \(urlRequest.httpMethod!)")
let encoding = JSONEncoding.default
print("yahoo was here \(params)")
//let facejsonData = try! JSONSerialization.data(withJSONObject: params!, options: JSONSerialization.WritingOptions())
return try encoding.encode(urlRequest, with: params!)
}
}
And, i call the API using the following function.
Alamofire.request(WINAPIRouter.create(params, nil)).responseJSON
I think response from API is not in JSON, try to use URL encoding like below,
Alamofire.request(path, method: .get, parameters: parameters, encoding: URLEncoding.default, headers: nil) . responseString(completionHandler: { ( dataResponse ) in
/// print response
})

Post method request Alamofire

I'm using Swift 3 and Alamofire 4.0.
I want to create similar Alamofire POST request as Postman request shown in screenshot:
I've tried with these lines of code:
var parameters: [String: Any] = [
"client_id" : "xxxxxx",
"client_secret" : "xxxxx",
"device_token" : "xxxx",
"fullname" : "xxxxx",
"gender": "xxx"
]
Alamofire.request(url, method: .post, parameters: parameters).responseJSON { response in
print(response)
}
But I got this error:
How to implement POST request with Body as form-data using Alamofire in Swift 3?
Swift 3.0 - Alamofire - Working code for multipart form data upload *
// Parameters
let params: [String : String] =
["UserId" : "\(userID)",
"FirstName" : firstNameTF.text!,
"LastName" : lastNameTF.text!,
"Email" : emailTF.text!
]
// And upload
Alamofire.upload(
multipartFormData: { multipartFormData in
for (key, value) in params
{
multipartFormData.append((value.data(using: .utf8))!, withName: key)
}
},
to: url,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
upload.uploadProgress(queue: DispatchQueue(label: "uploadQueue"), closure: { (progress) in
})
case .failure(let encodingError):
print(encodingError)
}
}
)
Let me know if you still have issues with it.
after too much try I have succeded so try this
override func viewDidLoad() {
super.viewDidLoad()
let parameters: Parameters = ["client_id": "1","user_token":"xxxxxxxx"]
// Do any additional setup after loading the view, typically from a nib.
let url = "http://xxxxxxxxxxx/index.php/Web_api/get_client_profile"
//let timeParameter = self.getLastTimeStamp()
self.request = Alamofire.request(url, method: .post, parameters:parameters)
if let request = request as? DataRequest {
request.responseString { response in
//PKHUD.sharedHUD.hide()
do{
let dictionary = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions.allowFragments) as! NSDictionary
print(dictionary)
}catch{
}
}
}
}
var request: Alamofire.Request? {
didSet {
//oldValue?.cancel()
}
}
You can post a request using Alamofire.
let url = ""
let headers = [ "Content-Type" : "application/json"]
let para : Parameters = [ "data" : JSONObject]
Alamofire.request(url, method: .post, parameters: para, encoding: JSONEncoding.default, headers : headers)
.responseJSON { response in
print(response)
print(response.result)
}
Nothing to worry about.
Alamofire request method not changed so much(For Swift 3.0) if in case you know how to do that in Swift 2.0/2.2. If you understand the old method then you can easily understand this one also. Now lets take a closer look on the following boilerplate -
Alamofire.request(apiToHit, method: .post, parameters: parametersObject, encoding: JSONEncoding.default, headers: headerForApi).responseJSON { response in switch response.result{
case .success(_):
if let receivedData: Any = response.result.value{
if let statusCode: Int = response.response?.statusCode {
//Got the status code and data. Do your data pursing task from here.
}
}else{
//Response data is not valid, So do some other calculations here
}
case .failure(_):
//Api request process failed. Check for errors here.
}
Now here in my case -
apiToHit //Your api url string
.post //Method of the request. You can change this method as per you need like .post, .get, .put, .delete etc.
parametersObject // Parameters needed for this particular api. Same in case you are sending the "body" on postman etc. Remember this parameters should be in form of [String: Any]. If you don't need this then you can just pass nil.
JSONEncoding.default //This the encoding process. In my case I am setting this as .default which is expected here. You can change this to .prettyPrinted also if you need.
headerForApi //This is the header which you want to send while you are requesting the api. In my case it is in [String: String] format. If you don't need this then you can just pass nil.
.responseJSON //Expecting the response as in JSON format. You can also change this as you need.
Now, in my request I am using Switch inside the request closure to check the result like response in switch response.result{.
Inside case .success(_): case I am also checking for result data and http status code as well like this
if let receivedData: Any = response.result.value{
if let statusCode: Int = response.response?.statusCode {
}
}
Hope this helped. Thanks.
class func alamofireMethod(methods: Alamofire.HTTPMethod , url : URLConvertible , parameters : [String : Any],need_flag_inside : Bool = false, paramJson : Bool = true ,need_loader : Bool = true,Header: [String: String],handler:#escaping CompletionHandler,errorhandler : #escaping ErrorHandler)
{
if NetworkController.sharedInstance.checkNetworkStatus()
{
var alamofireManager : Alamofire.SessionManager?
var hed = Header
if let tok = UserDefaults.standard.value(forKey: "TOKEN") as? String {
hed = ["Authorization":"Bearer \(tok)"]
}
if need_loader {
// DELEGATE.showLoader()
}
var UrlFinal = ""
do
{
try UrlFinal = baseURL + url.asURL().absoluteString
}
catch{}
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForResource = 25
configuration.timeoutIntervalForRequest = 25
configuration.httpAdditionalHeaders = hed
alamofireManager = Alamofire.SessionManager(configuration: configuration)
alamofireManager = Alamofire.SessionManager.default
let json = JSON(parameters)
guard let jsonDict = json.dictionaryObject else {
return
}
var jsonData = Data()
do {
jsonData = try JSONSerialization.data(withJSONObject: jsonDict, options: [])
} catch {
//handle error
print(error)
}
var request = URLRequest(url: URL(string: UrlFinal)!)
request.httpMethod = methods.rawValue
if methods == .post || methods == .put
{
//check here
if paramJson {
hed["Content-Type"] = "application/json"
request.httpBody = jsonData
}else{
let postString = self.getPostString(params: parameters)
request.httpBody = postString.data(using: .utf8)
}
}
request.allHTTPHeaderFields = hed
Alamofire.request(request).responseJSON(queue: nil, options: JSONSerialization.ReadingOptions.allowFragments) { (response) in
print(parameters)
print(UrlFinal)
print(hed)
// DELEGATE.hideLoader()
if response.result.isSuccess
{
print(response)
handler(response.result.value! as AnyObject)
}
else if response.response?.statusCode == 401
{
// DELEGATE.redirectToLogin()
// DELEGATE.showToast(message: "Token Expired")
}
else{
// DELEGATE.showToast(message: default_failure)
errorhandler(response.result.error! as NSError)
print(response.result.error as Any)
}
}
}else{
// DELEGATE.showToast(message: "Please check your internet connection.")
}
}
Alomofire With Post and Put Method In swift

Resources