How to implement the Bearer Token to validate the API url - ios

I set up the API and all, the only thing is Bearer Token I couldn't find any information about any code on how to implement it so it can validate the URL I am using as API.
do I need to create new swift file just for bearer token or I can write the code to the API swift file "the code below is api file"
static let shared = APICaller()
private let baseURL = "http://000.000.000.000:3030/api/"
private init() {}
var vehicles = [Vehicles]()
func getVehicles(for id: String, IMEI: Int, completed: #escaping (Result<[Vehicles],Errors>) -> Void ){
let endpoint = baseURL + "GetVehicle/?UserIdentificationValue=346HIU4623UIHG3I3I&IMEI=216216123612"
guard let url = URL(string: endpoint) else {
completed(.failure(.invalidURL))
return
}
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let _ = error {
completed(.failure(.unableToComplete))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}
guard let data = data else {
completed(.failure(.invalidData))
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
self.vehicles = try JSONDecoder().decode([Vehicles].self, from: data)
DispatchQueue.main.async {
completed(.failure(.invalidData))
}
} catch {
completed(.failure(.invalidData))
}
}
task.resume()
Thanks In Advance
Also I am new to swift so I would appreciate if you can tell me my API code is correct or needs any fixes since its about receiving some car info and putting into a table view cell :)

I have attached the request including headers in which you need to pass Bearer token like did in below code
let headers = [
"content-type": "application/json",
"authorizetoken": "NjQzOPA2N0NDNDFAH4CNDk3R23F2FQUY0NjV3FFE=",
"cache-control": "no-cache",
]
let parameters = ["id":"123456789"] as [String : Any]
let postData = try? JSONSerialization.data(withJSONObject: parameters, options: [])
let request = NSMutableURLRequest(url: NSURL(string: "Your URL")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 120.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as? Data
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData

Related

How to validate that my API Code is returning data

I just want to know if this code I wrote is returning data and I wanted the community to help achieve it since I am new to swift, I don't know where to put the print() function just to see if data is being shown on CLI output
class APICaller {
static let shared = APICaller()
private let baseURL = "http://000.000.000.000:0000/api/"
private init() {}
func getVehicles(for id: String, IMEI: Int, completed: #escaping (Result<[Vehicles],OnTraErrors>) -> Void ){
let endpoint = baseURL + "GetVehicles/?UserIdentificationValue=GASGSDG43848B497FE4604352GGS"
let headers = [
"content-type": "application/json",
"authorizetoken": "NjQzODM2N0NDNDM4NDhCNDk3RkU0NjGSAG4sg3=",
"cache-control": "no-cache",
]
guard let url = URL(string: endpoint) else {
completed(.failure(.invalidURL))
return
}
var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 120)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let task = session.dataTask(with: request) { data, response, error in
if let _ = error {
completed(.failure(.unableToComplete))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}
guard let data = data else {
completed(.failure(.invalidData))
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let vehicles = try decoder.decode([Vehicles].self, from: data)
completed(.success(vehicles))
} catch {
completed(.failure(.invalidData))
}
}
task.resume()
}
}

(Application.Errors.invalidResponse) Cant fix invalidResponse error

I don't get it why its showing invalidResponse as error when I think I did it all right the Token is correct the api URL is correct and tested on Postman, but when debugging its showing error at invalidResponse or invalidData after the response error, I haven't yet tried to fill TableView with the incoming api data fields because I want to try first if its coming before proceeding :( :)
class APICaller {
static let shared = APICaller()
private let baseURL = "http://000.000.000.000:3030/api/"
private init() {}
func getVehicles(for id: String, completed: #escaping (Result<[Vehicles],OnTraErrors>) -> Void ){
let endpoint = baseURL + "GetVehicles?UserIdentificationValue=\(id)"
guard let url = URL(string: endpoint) else {
completed(.failure(.invalidURL))
return
}
var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 120)
request.httpMethod = "GET"
request.allHTTPHeaderFields = [
"content-type": "application/json",
"authorizetoken": "Bearer NjQzODM2N0NDNDM4NDhCNDk3RkU0NjA0QUY0NjVFS3GE=",
"cache-control": "no-cache",
]
let session = URLSession.shared
let task = session.dataTask(with: request) { data, response, error in
if let _ = error {
completed(.failure(.unableToComplete))
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
completed(.failure(.invalidResponse))
return
}
guard let data = data else {
completed(.failure(.invalidData))
return
}
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let vehicles = try decoder.decode([Vehicles].self, from: data)
completed(.success(vehicles))
} catch {
completed(.failure(.invalidData))
}
}
task.resume()
}

Swift-4 : How to fetch data using POST request with Parameters in URLSession with "Content-Type" : "application/x-www-form-urlencoded"

Friends, I've gone through lot's of examples, which are available on S.O. Though I haven't received proper answer, and still I'm facing issue in getting data via api request using URLSession with Post request & passing parameters with it.
First, I'ld like to show you, what I have. tried till now...
func requestApiCall(){
let renewal_id = ""
let policy_no = ""
let client_name = ""
let client_id = ""
let product_name = ""
let created_date_from = ""
let created_date_to = ""
let policy_expiry_from = ""
let policy_expiry_to = ""
self.parameters = ["renewal_id":renewal_id,"policy_no":policy_no,"client_name":client_name,"client_id":client_id,"product_name":product_name,"created_date_from":created_date_from,"created_date_to":created_date_to,"policy_expiry_from":policy_expiry_from,"policy_expiry_to":policy_expiry_to]
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = [
"Accept" : "application/json",
"Content-Type" : "application/x-www-form-urlencoded"
]
let session = URLSession(configuration: config)
let Url = String(format: "http://myapi-url");
let serviceUrl = URL(string: Url)
var request = URLRequest(url: serviceUrl!)
print(request.url!)
request.httpMethod = "POST"
request.timeoutInterval = 60
request.httpBody = try! JSONSerialization.data(withJSONObject: parameters!, options: [])
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if error == nil{
print(response!)
}
else {
print(error?.localizedDescription as Any)
}
print(response!)
guard let httpResponse = response as? HTTPURLResponse, let receivedData = data
else {
print("error: not a valid http response")
return
}
switch (httpResponse.statusCode)
{
case 200: //The request was fulfilled
let response = NSString (data: receivedData, encoding: String.Encoding.utf8.rawValue)
if response == "SUCCESS"
{
print("Network - HandShaking Successfull...!!!")
}
else{
print("Network - HandShaking is not successfull...!!!")
}
case 400:
print("response-status - 400 : The request had bad syntax or was inherently impossible to be satisfied.")
case 500:
print("\nresponse-status - 500 : Internal Server Error...!!!")
default:
print("response-status - Unknown : Received Response => \(httpResponse.statusCode)")
}
})
task.resume()
}
After running above function, I'm getting httpResponse.statusCode = 500
But when I run this in postman, I get response properly, as aspected.
Postman Api-Request
Also I have tried to generate code-snippets through postman...which are as follow...
func postmanSnippetApiCall(){
let headers = [
"Content-Type": "application/x-www-form-urlencoded",
"cache-control": "no-cache",
"Postman-Token": "5d571157-86c5-4eac-ba6d-b00779ae5dbd"
]
let postData = NSMutableData(data: "renewal_id=".data(using: String.Encoding.utf8)!)
postData.append("&policy_no=".data(using: String.Encoding.utf8)!)
postData.append("&client_name=".data(using: String.Encoding.utf8)!)
postData.append("&client_id=".data(using: String.Encoding.utf8)!)
postData.append("&product_name=".data(using: String.Encoding.utf8)!)
postData.append("&created_date_from=".data(using: String.Encoding.utf8)!)
postData.append("&created_date_to=".data(using: String.Encoding.utf8)!)
postData.append("&policy_expiry_from=".data(using: String.Encoding.utf8)!)
postData.append("&policy_expiry_to=".data(using: String.Encoding.utf8)!)
postData.append("&undefined=undefined".data(using: String.Encoding.utf8)!)
let request = NSMutableURLRequest(url: NSURL(string: "http://myapiurl")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
}
But in postman generated code snippet, I'm receiving error on this line i.e request.httpBody = postData as Data and error is this one : Cannot convert value of type 'NSMutableData' to type 'Data' in coercion
If I use thirdParty Library i.e Alamofire, then I'm able to get data very easily.
Alamofire code snippet...runs perfectly..& gives proper response.
func apiRequestByAlamofire(){
let urlString = "http://myapiurl"
let params: [String: Any]? = ["renewal_id":"","policy_no":"","client_name":"","client_id":"","product_name":"","created_date_from":"","created_date_to":"","policy_expiry_from":"","policy_expiry_to":""]
Alamofire.request(urlString, method: .post, parameters: params).responseJSON { response in
print(response) //Here getting perfect response successfully...!!!
}
}
But still I'm struggling this via URLSession...!!!
And still I doubt, that why I'm getting too much problems, while doing with URLSession.
Friends for above my doubt, please I'm open to your suggestions, as well as please help me out to understand it.
Don't know, where am I going wrong. please help me out here.
After searching and fighting a lot with this I have come up with this solution:
guard var components = URLComponents(url: URL(string: "http://example.com")!, resolvingAgainstBaseURL: true)
else { fatalError("Couldn't create URLComponents") }
components.queryItems = params.map { k, v in URLQueryItem(name: k, value: v) }
var request = URLRequest(url: baseUrl.appendingPathComponent(path.rawValue))
request.httpBody = Data(components.query!.utf8)
request.httpMethod = "POST"
The "example.com" can literally be that, because I'm just using URLComponents to encode the parameters.
I am giving you simple function, You can edit this function as per your requirement. You can change your URL and params as well. And in the response, I have written two-line if you are taking JSON array from the server then use the first one if you are taking object then second one else remove Both lines.
func abc() {
let request = NSMutableURLRequest(url: URL(string: "Your URL")!)
request.httpMethod = "POST"
let postString = "param_name_one=\( value_1 )&param_name_two=\(value_2)&........."
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if(error != nil){
// Show Error Message
} else{
do {
//For JSON ARRAY
let jsonItem = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSArray
let json = jsonItem[0] as AnyObject
//For JSON object
let json_object = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as AnyObject
print(json_object)
} catch {
}
}
}
task.resume();
}

Post request with HTTP header parameters

I Want to use Bittrex api. I've read their api docs. There are explanations like the following.
For this version, we use a standard HMAC-SHA512 signing. Append apikey
and nonce to your request and calculate the HMAC hash and include it
under an apisign header.
$apikey='xxx';
$apisecret='xxx';
$nonce=time();
$uri='https://bittrex.com/api/v1.1/market/getopenorders?apikey='.$apikey.'&nonce='.$nonce;
$sign=hash_hmac('sha512',$uri,$apisecret);
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('apisign:'.$sign));
$execResult = curl_exec($ch);
$obj = json_decode($execResult);
I want to do this with Swift. But I don't want to use Alamofire.
I wrote a code. I think I'm doing everything but I'm getting the following error.
{
message = "APISIGN_NOT_PROVIDED";
result = "<null>";
success = 0;
}
I wrote similar code with Delphi. It works fine. So there is no problem with APIKEY. When I use the same parameters in Delphi, the same SecretHex is generated. So there's no problem with Encryption.
I think, I cannot do the Post Request with headers.
I can not find the fault. Would you please help me.
func getBalances()
{
let apiKeySTR = "01235xxxxxx"
let secretSTR = "41691xxxxxx"
let path = "https://bittrex.com/api/v1.1/account/"
let timeInterval = NSDate().timeIntervalSince1970
let epochtime = String(floor(timeInterval))
let urlFull = path + "getbalances" + "?" + "apikey=" + apiKeySTR + "&" + "nonce=" + epochtime
let secretUInt8 : [UInt8] = Array(urlFull.utf8)
var secretKey : [UInt8]?
do {
try secretKey = HMAC(key: secretSTR, variant: .sha512).authenticate(secretUInt8)
} catch {
print ("Error")
}
let secretHex = secretKey?.toHexString() ?? ""
guard let url = URL(string: urlFull) else { return }
var request = URLRequest(url: url)
request.addValue("apising", forHTTPHeaderField: (secretHex))
request.httpMethod = "POST"
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()
}
First off... you have a typo:
request.addValue("apising", forHTTPHeaderField: (secretHex))
I believe it's apisign, not "apising", right?
And below is a recap on creating REST API requests with a header and body. You can update this method according your needs:
1) Create URLRequest
var request = URLRequest(url: requestURL)
2) Set headers and http method:
request.allHTTPHeaderFields = ["Authentication" : "Bearer XYZ..."]
request.httpMethod = "POST"
3) Set request body:
// parameters is a simple [String:String] dictionary, just as header
let jsonData = try? JSONSerialization.data(withJSONObject: parameters)
request.httpBody = jsonData
Complete example:
public enum RESTMethod:String {
case get = "GET"
case post = "POST"
case put = "PUT"
}
public func sendRequest(_ url: String,
method: RESTMethod,
headers: [String : String],
parameters: [String : Any],
completionHandler: #escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionTask! {
let requestURL: URL
if method == .get {
let parameterString = parameters.stringFromHttpParameters()
requestURL = URL(string:"\(url)?\(parameterString)")!
} else {
requestURL = URL(string: url)!
}
var request = URLRequest(url: requestURL)
request.allHTTPHeaderFields = headers
request.httpMethod = method.rawValue
if method == .post {
let jsonData = try? JSONSerialization.data(withJSONObject: parameters)
request.httpBody = jsonData
}
request.timeoutInterval = 60
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
completionHandler(data,response,error)
}
task.resume()
return task
}
extension Dictionary {
/// Build string representation of HTTP parameter dictionary of keys and objects
func stringFromHttpParameters() -> String {
let parameterArray = self.map { (key, value) -> String in
let percentEscapedKey = (key as! String).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
let percentEscapedValue = (value as? String ?? "\(value)").addingPercentEncodingForURLQueryValue()!
return "\(percentEscapedKey)=\(percentEscapedValue)"
}
return parameterArray.joined(separator: "&")
}
}
Usage:
sendRequest("http://yourserver",
method: .get, // .post or .put
headers: [],
parameters: [],
completionHandler: { (data, response, error) in
// Handle response here
})

Using Yelp Fusion API in swift app not authenticating, continuously receiving "VALIDATION_ERROR"

Code here
let link = "https://api.yelp.com/oauth2/token"
guard let url = URL(string: link) else { return }
// Headers
let headers = [
"content-type": "application/x-www-form-urlencoded"
]
guard let clientID = infoPlist(withKey: "YELP_API_CLIENT_ID"),
let clientSecret = infoPlist(withKey: "YELP_API_CLIENT_SECRET") else { return }
let body = "client_id=\(clientID)&client_secret=\(clientSecret)&grant_type=client_credentials"
var request = URLRequest.init(url: url)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = body.data(using: .utf8)
As far as I know this should be working. Based on everything I've read this is the proper process for authenticating with Yelp Fusion/v3.
You didn't post your entire code, but with some slight modifications your code works:
let appId = "xxx"
let appSecret = "yyy"
let link = "https://api.yelp.com/oauth2/token"
let url = URL(string: link)!
let bodyData = "client_id=\(appId)&client_secret=\(appSecret)&grant_type=client_credentials".data(using: .utf8)!
// Headers
let headers = [
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": "\(bodyData.count)"
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = bodyData
typealias JSON = [String:Any]
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data,
let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
print(error!)
return
}
if let responseJSON = try? JSONSerialization.jsonObject(with:data, options:[]),
let parsedJSON = responseJSON as? JSON {
let token = parsedJSON["access_token"]
let exipration = parsedJSON["expires_in"]
}
}.resume()

Resources