API call is giving outdated response in swift - ios

I am making a HTTP get request in swift where I am getting an outdated response for some reason..I have compared the response in Postman with the one I printed in the Xcode and I'm getting this..
Response Headers in Postman:
Response Headers printed in Xcode Console:
see the sections highlighted in green, both the calls are made at the same time. This is a live API of my project and as there is no change in the current live data I am not showing JSON response. But as you can see in the response headers, the value for field "Date" in both Postman and Xcode is different.. When I do it in Postman, it is giving me new response every time. But in Xcode I'm getting the same response all day. I don't know why This is happening. And after erasing the contents of simulator (or deleting the app from simulator) and reinstalling the project again it gave me a new updated response. But it's again repeated...
Code in RequestManager Class:
import Foundation
class RequestManager {
class func callTheGetAPI(urlString: String, closure: #escaping (Data?)->Void) {
let url = URL.init(string: urlString)
var urlRequest = URLRequest(url: url!)
urlRequest.httpMethod = "GET"
urlRequest.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if (error != nil) {
print(error!.localizedDescription)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse!.allHeaderFields)
closure(data)
}
}
dataTask.resume()
}
}
code in my ViewController:
override func viewDidLoad() {
super.viewDidLoad()
getRecommendedData()
}
func getRecommendedData() {
let url = APIManager.API_01
RequestManager.callTheGetAPI(urlString: url, closure: { response in
do {
if (try JSONSerialization.jsonObject(with: response!, options: .mutableContainers) as? [[String : Any]]) != nil{
// print(json)
}
} catch let error {
print(error.localizedDescription)
}
})
}
This is all I have guys.. If anyone knows what's happening or if I'm doing something wrong.. Please help..

Replace below line
var urlRequest = URLRequest(url: url!)
With
var urlRequest = URLRequest(url: url!, cachePolicy: URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 60)
From the documentation reloadIgnoringCacheData: Specifies that the
data for the URL load should be loaded from the origin source. No
existing local cache data, regardless of its freshness or validity,
should be used to satisfy a URL load request.
By default it uses caches.

Related

URLSession not sending codable struct as request body

i am trying to send a POST API call with URLSession, but it is not sending requset body.
my sturct is a Codable sturct, and APi works in Postman
here is my code
var urlRequest = URLRequest(url: URL(string: EndPoint.BASE_URL + "SignUp")!)
urlRequest.httpMethod = "post"
do {
let requestBody = try JSONEncoder().encode(self)
urlRequest.httpBody = requestBody
urlRequest.addValue("application/json", forHTTPHeaderField: "content-type")
} catch let error {
debugPrint(error.localizedDescription)
}
URLSession.shared.dataTask(with: urlRequest) { (data, httpUrlResponse, error) in
if(data != nil && data?.count != 0)
{
guard let data = data else {return }
do
{
let response = try JSONDecoder().decode(SignUpResponse.self, from: data)
completion(.success(response))
}
catch let decodingError {
debugPrint(decodingError.localizedDescription)
}
}
}.resume()
can you please look, where i am missing anything.
since your request structure inherits from the codable type alias, I think all you have to do is replace the code
let requestBody = try JSONEncoder().encode(self)
with
let requestBody = try JSONEncoder().encode(YOUR_REQUEST_STRUCTURE)
apart from that all looks good and also as a sanity check add a debugger to the URLRequest and validate if the URLRequest is generating the correct SignUp URL that matches the one you have in the postman.
Also its a wise idea to not to use Codable for your request models and just implement the Encodable protocol unless you need to.

Sending HTTP POST request with Swift to Discord Webhook results in Response Error

I'm trying to create a URL Request in Swift to send an HTTP POST request to a Discord Webhook, and the request completes in a failure defined as 'responseProblem'. I'm not sure where the response problem is originating from.
Discord should technically be able to accept HTTP requests, and a bunch of research into the issue has led me nowhere. I've worked with Discord webhooks before, but I've never played around with this kind of stuff before, so I'm kinda stuck for what I should do now.
import Foundation
enum APIError:Error {
case responseProblem
case decodingProblem
case encodingProblem
}
struct APIRequest {
let resourceURL: URL
init(endpoint: String) {
let resourceString = "<discord-webhook-url-removed-for-privacy>"
guard let resourceURL = URL(string: resourceString) else {fatalError()}
self.resourceURL = resourceURL
}
func save (_ messageToSave:Message, completion: #escaping(Result<Message, APIError>) -> Void ) {
do {
var urlRequest = URLRequest(url: resourceURL)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpBody = try JSONEncoder().encode(messageToSave)
let dataTask = URLSession.shared.dataTask(with: urlRequest) { data, response, _ in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, let
jsonData = data else {
completion(.failure(.responseProblem)) // <<< 'responseProblem' is outputted in console as the error
return
}
do {
let messageData = try JSONDecoder().decode(Message.self, from: jsonData)
completion(.success(messageData))
} catch {
completion(.failure(.decodingProblem))
}
}
dataTask.resume()
} catch {
completion(.failure(.encodingProblem))
}
}
}
When I run this Swift program, I expected it to send a request to the Discord Webhook to send a message into it's designated channel. However, the only error outputted into the console is responseProblem. Please let me know if there is anything further I need to add to get the root cause of the problem (I'm still semi-fresh to Swift, and I normally work with JavaScript, so I'm not sure how to properly debug in Swift and Xcode.)
Swift app is built in iOS 12.2 because Xcode doesn't like this stuff in iOS 13
This is a simplified version of how I post to a Discord webhook with Swift. From your post I can't see how you're converting your custom Message struct into a JSON dictionary, but you need at least the key/value pair for "content" to successfully post a Discord Webhook. And of course the posts can be customized in many other ways (with a custom "username" etc.).
var messageString: String = ""
guard let url = URL(string: "your-full-discord-webhook-url") else { return }
let messageJson: [String: Any] = ["content": messageString]
let jsonData = try? JSONSerialization.data(withJSONObject: messageJson)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "content-type")
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request)
task.resume()

How to pass bearer token to make Yelp API call with URLSessoin

U P D A T E D... The function with what works!
I would like to incorporate the yelp api into an app but can't successfully pass my authorization token on the URL string. Do I need to do something to connect the URLRequest to the URLSessoin call and its not using the header? Maybe the key value pairs is wrong? The below function returns:
error = {
code = "TOKEN_MISSING";
description = "An access token must be supplied in order to use this endpoint.";
};
I was able to use postman to get the yelp API call working, but only by clicking the "Header" section on postman and putting in Bearer and then my yelp key. I googled around a bit and found some links that indicate that you can add a header to the URLSession that I assume would work the way postman does but I haven't been able to get it to work.
I know there are some githubs with yelp API repos but I am trying to not install a large set of code that I don't understand into my app, when all I want is the JSON that I can see is coming through on postman. Can anyone help me understand how I would edit code similar to the Here example below so that I can get the Authorization/Bearer that yelp requires?
func getYelp() {
let appSecret = "Bearer <YELP APIKEY>"
let link = "https://api.yelp.com/v3/businesses/search?latitude=37.786882&longitude=-122.399972"
if let url = URL(string: link) {
// Set headers
var request = URLRequest(url: url)
request.setValue("Accept-Language", forHTTPHeaderField: "en-us")
request.setValue(appSecret, forHTTPHeaderField: "Authorization")
print("Attempting to get places around location from Yelp")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil {
print(error!)
} else {
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject // Added "as anyObject" to fix syntax error in Xcode 8 Beta 6
print("Printing all JSON/n/n//n--------------------------")
print(jsonResult)
print("Printing from results/n/n//n--------------------------")
if let description = ((jsonResult["search"] as? NSDictionary)?["context"] as? NSDictionary)?["href"] as? String {
} else {
print("JSON pull failed/n/n//n--------------------------")
}
} catch {
print("JSON Processing Failed/n/n//n--------------------------")
}
}
}
}
task.resume()
} else {
resultLabel.text = "Couldn't get results from Here"
}
}
You're mixing up between the headers and the url, you need to set your headers correctly
if let url = URL(string: "https://places.cit.api.here.com/places/v1/discover/around?at=37.776169%2C-122.421267&app_id=\(app_id)&app_code=\(app_code)") {
var request = URLRequest(url: url)
// Set headers
request.setValue("Accept-Language", forHTTPHeaderField: "en-us")
request.setValue("Authorization", forHTTPHeaderField: "Bearer " + token // Token here)
print("Attempting to get places around location")
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
// ...
Lets say you have an api with "https://google.com" (this is just an example with fake keys)
and an api key that is "ApiKey: 92927839238293d92d98d98d92".
You would then take this information and do this.
let uri = URL(string:"https://google.com")
if let unwrappedURL = uri {
var request = URLRequest(url: unwrappedURL)request.addValue("92927839238293d92d98d98d92", forHTTPHeaderField: "ApiKey")
let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
// you should put in error handling code, too
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
// HERE'S WHERE YOUR DATA IS
print(json)
} catch {
print(error.localizedDescription)
}
}
}
dataTask.resume()
}
Please remember that you would replace the google.com with your GET address and the APIKey header with your own api key values.
Also, this will print out all the JSON like in PostMan.
If this works for you, then I also have a link on accessing the JSON Objects.

My url is not responding

Hi there I'm trying to make a post request so I made a class, a simple class to test the url but is not responding, I mean I can use other url different to the url that I suppose to use and It's responding so the request it's ok what is not working is the url. The weird thing is that in postman the url is working the server response ok. I also enable the app transport security allow arbitrary load to yes and still not working could you have any idea why is this? Thanks in advance.
Here is my code
#IBAction func buton(_ sender: Any) {
let parameters: [String : Any] = ["acceptPrivacyNotice": true,
"name": "xxxx xxxx",
"email":"xxx#mail.com",
"password": "qwerty2012",
"passwordConfirm": "qwerty2012",
"deviceID": "",
"isProvider": false,
"idTypeProvider":1 ]
guard let url = URL(string: "https://www.apps-sellcom-dev.com/Engie/api/account/register") else {return}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("YOURAPIKEY==", forHTTPHeaderField: "Authorization")
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",response)
}
if let data = data {
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
}
}.resume()
}
The certificate of the domain is about to expire, so I guess thats why the URL wasn't found.
I enabled the app transport security and set the URL in the info.plist using LSApplicationQueriesSchemes, and now I'm getting a response from the server.

Swift POST request sends an empty body

Here's the code:
func makePOSTCall(endpoint: String, languageName: String) {
guard let url = URL(string: endpoint) else {
print("Could not create URL.")
return
}
let requestLang: [String: Any] = ["name": languageName]
let requestBody = try? JSONSerialization.data(withJSONObject: requestLang)
var urlRequest = URLRequest(url: url)
urlRequest.httpBody = requestBody
urlRequest.httpMethod = "POST"
let session = URLSession.shared
let task = session.dataTask(with: urlRequest) {
data, response, error in
guard let data = data, error == nil else {
print(error?.localizedDescription ?? "No data")
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseJSON = responseJSON as? [String: Any] {
print(responseJSON)
}
}
task.resume()
}
This sends a {"name": "Go"} JSON dictionary to Flask. Flask is supposed to append the language name to an array and return the full array in the response. Now, this works when I send the request manually, so it's not Flask's error. But when I send the above from iOS, I get request.json == None in the flask console. Clearly, I'm sending an empty body, but I shouldn't be. Any idea where I went wrong?
I call the function as
#IBAction func pressedMakePOSTCall(_ sender: UIButton) {
makePOSTCall(endpoint: "http://127.0.0.1:5000/lang", languageName: "Go")
}
I tried adding a trailing slash, just get a 404 in the console. The only question similar to mine that I've found is this: How to make HTTP Post request with JSON body in Swift and my code is basically identical.
#weissja19 was correct, I needed to set content type to application/json. Adding
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
fixed the error. Now the code works as I expected.
P.S. I couldn't catch it because I use the app Paw for testing, which sets content type automatically.
You might want to do it manually:
urlRequest.httpBody = "name=\(languageName)".data(using: .utf8)
Use JSONSerialization will make your POST body like {"name":"abc"} which might not be supported by your server

Resources