How to Compress UIIMage Using TinyPNG Swift - ios

I have a request in Swift 5 that is trying to make a call to tinify.com. It is supposed to give me back a URL to a compressed image. I am currently getting this error in the print field:
{"error":"Not found","message":"This endpoint does not exist."}
TinyPNG.com API Reference
Code:
let string = "https://api.tinify.com/shrink"
let url = NSURL(string: string)
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "GET"
request.addValue("fakeAPIKey1234", forHTTPHeaderField: "user api")
request.addValue("/dev/stdout", forHTTPHeaderField: "dump-header")
request.addValue("\(String(describing: self.jpegData(compressionQuality: 0.8)!))", forHTTPHeaderField: "data-binary")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
guard error == nil else { print(error!.localizedDescription); return }
guard let data = data else { print("Empty data"); return }
if let str = String(data: data, encoding: .utf8) {
print("Grab Image from this url: \(str)")
}
}
Note: fakeAPIKey1234 is not actually the string I'm using. Also I'm sure there is more wrong with my code than this little issue.

Related

Trying to add email contacts to Sendgrid

Problem: How can I add an email to a Sendgrid contact list in Swift?
Here's what I've done so far (this is not working)
var request = URLRequest(url: URL(string: sendGridURL)!)
request.httpMethod = "PUT"
let json = [
"listIds": ["a7aab3b0-0307-40e6-aa6f-7a3964b8fa1f", "0464f62d-9bb7-440c-8f64-ff2b66ec199b"],
"contacts": [[ "email" : "\(email)" ]]
];
//Headers
request.addValue("Bearer \(sendGridAPIKey)", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
do {
let data = try JSONSerialization.data(withJSONObject: json, options: [])
request.httpBody = data
} catch {
print("sendgrid \(error)")
}
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard error == nil else { print("sendgrid \(error!.localizedDescription)"); return }
guard let data = data else { print("sendgrid Empty data"); return }
if let str = String(data: data, encoding: .utf8) {
print("sendgrid \(str)")
}
}.resume()
}
The issue was I was using POST not PUT. Now, I'm having the issue where I cannot add contacts to a specific list.

HTTP Post request with body receiving null values to server

I am using trying to post some data to server using Swift URLRequest with using following code.
var request = URLRequest(url: URL(string: Global.ip)!)
request.httpMethod = "POST"
request.addValue("application/x-www-form-urlencoded; charset=UTF-8", forHTTPHeaderField: "Content-Type")
let postString = "cmd=getFavorites" + "&ab={\"userId\":\"\(userId)\",\"favId\":\"\(favoriteId)\",\"favoriData\":\(panelData)}&token=\(token)"
let newPostString = postString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
request.httpBody = newPostString?.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("error=\(String(describing: error))")
completion(false)
return;
}
let json = JSON(data)
completion(true)
}
task.resume()

Swift HTTP Post Request returns HTML of site instead of JSON response

I am trying to reach a site that should take the username and password given and return a JSON which contains information stating whether or not the login data provided was valid or not.
However, all I'm getting back is the site's HTML code instead of a response. I've tried the request with the same parameters on https://www.hurl.it/ and have gotten the correct response so that does not seem to be the issue.
I use the following code:
private func uploadToAPI(username: String, password: String) {
guard let url = URL(string: "http://api.foo.com/login.php"),
let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics),
let encodedPassword = password.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics) else {
self.loginButton.isLoading = false
return
}
let httpBodyParameters = ["user": encodedUsername, "password": encodedPassword, "client": "ios", "version": "5"]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: httpBodyParameters, options: JSONSerialization.WritingOptions.prettyPrinted)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let response = response {
print(response.mimeType) // Prints "text/html"
}
if let data = data {
print(try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)) // Prints nil
print(String(data: data, encoding: String.Encoding.utf8)) // Prints the site's HTML
}
}.resume()
}
I fail to see where the issue is. I've also tried not setting the HTTP headers but that makes no difference. Anyone got any ideas?
It seems like not setting the HTTP header fields and using a string literal instead of a Dictionary as HTTP body data did it for me.
For anyone interested this is the code that now receives the expected response:
guard let url = URL(string: "http://api.foo.com/login.php?"),
let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics),
let encodedPassword = password.addingPercentEncoding(withAllowedCharacters: CharacterSet.alphanumerics) else {
if let delegate = self.delegate {
delegate.viewModelDidRejectLogin(self)
}
return
}
let httpBodyString = "user=\(encodedUsername)&password=\(encodedPassword)&client=ios&version=5"
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = httpBodyString.data(using: String.Encoding.utf8)
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
print(error)
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data) as? [String : AnyObject] {
self.readLoginResponse(json)
}
} catch {
print(error)
}
}.resume()

Display UIActivityIndicator while loading API data safely

I'm working on this app and have developed a full API for it. However, now that I've come to the front end part (the IOS app), I'm not sure how to load that data the right way.
I have made this class to make requests a little bit easier, but I get confused when it comes to threading and that sort of stuff...
Basically, I have a simple UITableView set up, and I want it to display data that I fetch from my API. During fetching, I need it to display a UIActivityIndicator which has to hide automatically as well.
How the hell do I do this? (Especially the automatic UIActivityIndicator)
Here is my request struct:
//
// Request.swift
// Voots
//
// Created by Carlo on 16/10/2017.
// Copyright © 2017 Carlo. All rights reserved.
//
import Foundation
struct Request {
// Post request with specific url, parameters and token
func post(params: [String: String], url: String, token: String?,
completion: ((Data, URLResponse) -> ())?) {
let nsUrl = NSURL(string: url)
var request = URLRequest(url: nsUrl! as URL)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// If a token was provided, add it.
if token != nil {
request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
print(request.value(forHTTPHeaderField: "Authorization")!)
}
request.httpMethod = "POST"
guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions.prettyPrinted) else {
return
}
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let data = data {
if let response = response {
if completion != nil {
completion!(data, response)
}
}
}
}.resume()
}
func get(url: String, token: String?, completion: ((Data, URLResponse) -> ())?) {
let nsUrl = NSURL(string: url)
var request = URLRequest(url: nsUrl! as URL)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// If a token was provided, add it.
if token != nil {
request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
print(request.value(forHTTPHeaderField: "Authorization")!)
}
request.httpMethod = "GET"
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let data = data {
if let response = response {
if completion != nil {
completion!(data, response)
}
}
}
}.resume()
}
}
Here is list of readymade (available) libraries, if you don't want to add manual effort to manage this:
iOS Libraries - ActivityIndicatorView
MBProgressHUD
SVProgressHUD
Here is sample for you, how you can manage it.
class ViewController: UIViewController {
// Create an IBOutlet of indicator or you can create it programatically also.
#IBOutlet weak var activitIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
activitIndicator.isHidden = false
Request.post(params: <#T##[String : String]#>, url: <#T##String#>, token: <#T##String?#>) { (<#Data#>, <#URLResponse#>) in
DispatchQueue.main.async(execute: {
self.activitIndicator.isHidden = true
})
}
}
}
struct Request {
// Post request with specific url, parameters and token
// Note: use static function
static func post(params: [String: String], url: String, token: String?,
completion: ((Data, URLResponse) -> ())?) {
let nsUrl = NSURL(string: url)
var request = URLRequest(url: nsUrl! as URL)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// If a token was provided, add it.
if token != nil {
request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
print(request.value(forHTTPHeaderField: "Authorization")!)
}
request.httpMethod = "POST"
guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions.prettyPrinted) else {
return
}
request.httpBody = httpBody
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let data = data {
if let response = response {
if completion != nil {
completion!(data, response)
}
}
}
}.resume()
}
// Note: use static function
static func get(url: String, token: String?, completion: ((Data, URLResponse) -> ())?) {
let nsUrl = NSURL(string: url)
var request = URLRequest(url: nsUrl! as URL)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// If a token was provided, add it.
if token != nil {
request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
print(request.value(forHTTPHeaderField: "Authorization")!)
}
request.httpMethod = "GET"
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if let data = data {
if let response = response {
if completion != nil {
completion!(data, response)
}
}
}
}.resume()
}
}

Receive POST request from Swift in Node.js

I am trying to receive and process a POST request being sent from my iOS app to my Node.js web server. The server responds with HTTP Error 502 whenever I try to send this POST request. Could you please look at my code below and see what is wrong with it? Thank you!
Node.js Code
app.post('/applogin', function(req, res) {
var parsedBody = JSON.parse(req.body);
console.log(parsedBody)
});
Swift Code (POST function)
func httpPost(jsonData: Data) {
if !jsonData.isEmpty {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = jsonData
URLSession.shared.getAllTasks { (openTasks: [URLSessionTask]) in
NSLog("open tasks: \(openTasks)")
}
let task = URLSession.shared.dataTask(with: request, completionHandler: { (responseData: Data?, response: URLResponse?, error: Error?) in
NSLog("\(response)")
})
task.resume()
}
}
Swift Code (sending of the POST request)
#IBAction func onClick(_ sender: Any) {
let username = Username.text
let password = Password.text
var dataString = "username: \(username), password: \(password)"
let data = dataString.data(using: .utf8)
httpPost(jsonData: data!)
}
Thanks in advance!
You have to send a json instead dataString, and you have to set the "Content Type" header with value "application/json"
Swift 2
let request = NSMutableURLRequest(URL: requestUrl)
request.HTTPMethod = "POST"
let params = ["username" : username, "password" : password] as Dictionary<String, AnyObject>
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options:NSJSONWritingOptions.PrettyPrinted)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
Many answers they don't mention that we need to set header for the request from Swift side before sending to the backend otherwise it'll be a string in a wrong format that we can't use JSON.parse, here's what I firgured out (NOTE the IMPORTANT line):
let json = [
"email": emailTextField.text
]
let jsonData = try! JSONSerialization.data(withJSONObject: json)
let url = URL(string: BASE_URL + "/auth/register")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
// insert json data to the request
request.httpBody = jsonData
//IMPORTANT
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = URLSession.shared.dataTask(with: request) { 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()
And in your NodeJS with Express just call req.body and you're done
Try this:
app.post('/applogin', function(req, res) {
var parsedBody = JSON.parse(req.body);
console.log(parsedBody)
res.send("Request received")
});

Resources