Unsupported URL swift ios sending Http request - ios

I'm trying to send an http request in swift.
I got a method (sendHttpRequest) that take as argument a dictionary<String,AnyObject> and trying to send a request to localhost with a little server in php. When I tap button that call this function an error occur
"Optional(Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSErrorFailingURLStringKey=46.101.145.122/salvobertoncini.com/servo.php, NSErrorFailingURLKey=46.101.145.122/salvobertoncini.com/servo.php, NSLocalizedDescription=unsupported URL, NSUnderlyingError=0x1763cef0 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}})"
Here is the code:
func sendHttpRequests(data : Dictionary<String, AnyObject>)
{
let session = NSURLSession.sharedSession()
do
{
let request = try NSJSONSerialization.dataWithJSONObject(data, options: .PrettyPrinted)
let url = NSURL ( string : "127.0.0.1/Server/servo.php")
let finalRequest = NSMutableURLRequest(URL: url!)
finalRequest.HTTPMethod = "POST"
finalRequest.HTTPBody = request
let task = session.dataTaskWithRequest(finalRequest){ data,response,error in
if error != nil
{
print("Error -> \(error)")
}
do
{
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject]
print("Result -> \(result)")
}
catch
{
print("Error -> \(error)")
}
}
task.resume()
}
catch
{
print(error)
}
}

Related

Cannot trace on the status if connected to API Server or not

I am creating a sign in page where in connected to API to retrieve event details using passcode that will be inputted in a textfield, but the display message "Could not successfully perform this request. Please try again later" is the only thing that appears. I can't track if I have error in connection or the codes I wrote. Kindly help me and check my code if there is something wrong or missing. Thank you.
//Read values from textfield
let eventcode = appCodeTextField.text
//Check if required fields are not empty
if (eventcode?.isEmpty)!
{
//Display alert message here
self.displayMessage(userMessage: "Please input event code.")
print("empty")
return
}
//Send HTTP Request to perform Sign in
let myUrl = URL(string: "http://hopprlab.com/api/events/passcodechecker/(event_id)")
var request = URLRequest(url: myUrl!)
request.httpMethod = "POST" //Compose a query string
request.addValue("application/json", forHTTPHeaderField: "content-type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let postString = ["eventcode": eventcode!] as [String: String]
do
{
request.httpBody = try JSONSerialization.data(withJSONObject: postString, options: .prettyPrinted)
} catch let error {
print (error.localizedDescription)
displayMessage(userMessage: "Network Error!")
return
}
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
self.removeActivityIndicator(activityIndicator: myActivityIndicator)
if error != nil
{
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
print("error=\(String(describing: error))")
return
}
//Convert response sent to server side code to a NSDictionary object:
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
if let parseJSON = json {
if parseJSON["errorMessageKey"] != nil {
self.displayMessage(userMessage: parseJSON["errorMessage"] as! String)
return
}
//Now we can acess value
let event_id = parseJSON["event_id"] as? String
let saveEventId: Bool = KeychainWrapper.standard.set((event_id)!, forKey: "event_id")
print("The event id save result \(saveEventId)")
if (event_id?.isEmpty)!
{
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
return
}
DispatchQueue.main.async {
let dashBoardPage = self.storyboard?.instantiateViewController(withIdentifier: "DashBoardViewController") as! DashBoardViewController
let appDelegate = UIApplication.shared.delegate
appDelegate?.window??.rootViewController = dashBoardPage
}
} else {
//Display an Alert dialog with a friendly error message
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
}
} catch {
self.removeActivityIndicator(activityIndicator: myActivityIndicator)
//Display an Alert dialog with a friendly error message
self.displayMessage(userMessage: "Could not successfully perform this request. Please try again later")
print(error)
}
}
task.resume()

Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value.}

The method is working fine and it does what I want on the back-end but I am getting the following error in the console:
Error Domain=NSCocoaErrorDomain Code=3840 "No value."
UserInfo={NSDebugDescription=No value.}
The above error is caught in the catch.
I read out similiar questions which suggests to add value for the headers, but didn't fix it either.
let serverURL = URL(string: "https://xxx/xxx/xxx/xxx/xxx/email")
self.request = URLRequest(url:serverURL!)
self.request?.httpMethod = "POST"
self.request?.addValue("application/json", forHTTPHeaderField: "content-type")
self.request?.addValue("application/json", forHTTPHeaderField: "Accept")
do {
self.request?.httpBody = try JSONSerialization.data(withJSONObject: postContent, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
return
}
The json has this format: postContent: [String: String], ["email": "myemail#domain.com"]
The code for task:
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if (self.activityIndicator != nil) {
self.removeActivityIndicator(activityIndicator: self.activityIndicator!)
}
guard let data = data else {return}
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:String]
if let parseJSON = json {
self.alertMessage(message: "Please check your email for instructions.")
}
} else {
self.alertMessage(message: "Invalid email address!")
}
} catch {
self.alertMessage(message: "Could not send request. Try again!")
print(error)
}
}
task.resume()
I think you have a typo mistake. Did you try to change
self.request?.addValue("application/json", forHTTPHeaderField: "content-type")
to
self.request?.addValue("application/json", forHTTPHeaderField: "Content-Type")
I was getting 200 OK response but the json body was returned empty:
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:String]
I modified the API and added body to response to fix this.

Extra argument 'error' in call - Unable to build my Xcode project

import Foundation
class NetworkOperation {
lazy var config: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
lazy var session: NSURLSession = NSURLSession(configuration: self.config)
let queryURL: NSURL
typealias JSONDictionaryCompletion = ([String: AnyObject]? -> Void)
init(url: NSURL) {
self.queryURL = url
}
func downloadJSONFromURL(completion: JSONDictionaryCompletion) {
let request = NSURLRequest(URL: queryURL)
let dataTask = session.dataTaskWithRequest(request) {
(let data, let response, let error) in
// 1. Check HTTP response for successful GET request
if let httpResponse = response as? NSHTTPURLResponse {
switch httpResponse.statusCode {
case 200:
// 2. Create JSON object with data
let jsonDictionary = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil)
completion(jsonDictionary)
default:
print("GET request not successful. HTTP status code: \(httpResponse.statusCode)")
}
} else {
print("Error: Not a valid HTTP response")
}
}
dataTask.resume()
}
}
In the 'Create JSON object with data' step, I keep receiving the "extra argument 'error' in call". What is happening? I am unable to find documentation to help me further in this.
You can do it by this way.
do{
var jsonDictionary = try NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers)
//completion(jsonDictionary)
}catch{
// report error
}
at the top of step 2: creating json....
add this line:
var err: NSError?
// 1. Check HTTP response for successful GET request
if let httpResponse = response as? NSHTTPURLResponse {
switch httpResponse.statusCode {
case 200:
// 2. Create JSON object with data
let jsonDictionary = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [String: AnyObject]
completion(jsonDictionary)
default:
println("GET request not successful. HTTP status code: \(httpResponse.statusCode)")
}
} else {
println("Error: Not a valid HTTP response")
}
}
dataTask.resume()
}
}
Finally figured it out! Thank you for your input everyone!

Swift IOS: How to perform a REST POST request

I am trying to implement a POST with raw text to path, I have tried using NSMutableURLRequest and specifying the following
request.HTTPMethod = "POST"
request.HTTPBody = "some strings here"
I did not manage to get much further than that as I failed miserably while implementing the session.uploadTaskWithRequest.
This however is what I got working fine for a GET request;
private func get(path: String)
{
let url = NSURL(string: path)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
println("JSON recieved")
if(error)
{
println(error.localizedDescription)
}
println("Parsing JSON")
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err != nil)
{
println("Json error");
}
println("Building Array result list from JSON")
var results = jsonResult["results"] as NSArray
self.delegate?.didReceiveAPIResult(jsonResult)
println("Done with JSON response")
})
task.resume()
}
Here you go:
let request = NSMutableURLRequest(URL: yourURL)
request.HTTPMethod = "POST"
let data = yourString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().uploadTaskWithRequest(request,
fromData: data)
task.resume()

How do I perform GET and POST requests in Swift?

I adapted this from Ray Wenderlich's iOS Apprentice tutorial part 4.
This code works as a GET request sent to my Strongloop API with a simple database model, however:
This works, but I don't know why it works, since it invokes no method that I can see to actually send the request.
I see no means to make it into a POST request.
My question is: How do I perform a POST request? Is it done in a completely different way?
Let me know if you need more information.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func getFromDB() {
let url = urlWithSearchText("")
println("URL: '\(url)'")
if let jsonString = performGetRequestWithURL(url) {
println("Received JSON string '\(jsonString)'")
}
}
func urlWithSearchText(searchText: String) -> NSURL {
let escapedSearchText = searchText.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
let urlString = String(format: "http://localhost:3000/api/Tests", escapedSearchText)
let url = NSURL(string: urlString)
return url!
}
func performGetRequestWithURL(url: NSURL) -> String? {
var error: NSError?
if let resultString = String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error) {
return resultString
} else if let error = error {
println("Download Error: \(error)")
} else {
println("Unknown Download Error")
}
return nil
}
Here is a picture of this working:
https://dl.dropboxusercontent.com/u/14464971/Images/Messages%20Image%281477993527%29.png
Swift 3 & above
GET
func getRequest() {
// request url
let url = URL(string: "https://jsonplaceholder.typicode.com/todos/1")! // change the url
// create URLSession with default configuration
let session = URLSession.shared
// create dataTask using the session object to send data to the server
let task = session.dataTask(with: url) { data, response, error in
if let error = error {
print("GET Request Error: \(error.localizedDescription)")
return
}
// ensure there is valid response code returned from this HTTP response
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("Invalid Response received from the server")
return
}
// ensure there is data returned
guard let responseData = data else {
print("nil Data received from the server")
return
}
do {
// serialise the data object into Dictionary [String : Any]
if let jsonResponse = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers) as? [String: Any] {
print(jsonResponse)
} else {
print("data maybe corrupted or in wrong format")
throw URLError(.badServerResponse)
}
} catch let error {
print("JSON Parsing Error: \(error.localizedDescription)")
}
}
// resume the task
task.resume()
}
POST
func postRequest() {
// declare the parameter as a dictionary that contains string as key and value combination. considering inputs are valid
let parameters: [String: Any] = ["name": "abc", "password": "password#123"]
// create the url with URL
let url = URL(string: "http://myServerName.com/api")! //change the url
// create the session object
let session = URLSession.shared
// now create the URLRequest object using the url object
var request = URLRequest(url: url)
request.httpMethod = "POST" //set http method as POST
// add headers for the request
request.addValue("application/json", forHTTPHeaderField: "Content-Type") // change as per server requirements
request.addValue("application/json", forHTTPHeaderField: "Accept")
do {
// convert parameters to Data and assign dictionary to httpBody of request
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
return
}
// create dataTask using the session object to send data to the server
let task = session.dataTask(with: request) { data, response, error in
if let error = error {
print("Post Request Error: \(error.localizedDescription)")
return
}
// ensure there is valid response code returned from this HTTP response
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode)
else {
print("Invalid Response received from the server")
return
}
// ensure there is data returned
guard let responseData = data else {
print("nil Data received from the server")
return
}
do {
// create json object from data or use JSONDecoder to convert to Model stuct
if let jsonResponse = try JSONSerialization.jsonObject(with: responseData, options: .mutableContainers) as? [String: Any] {
print(jsonResponse)
// handle json response
} else {
print("data maybe corrupted or in wrong format")
throw URLError(.badServerResponse)
}
} catch let error {
print(error.localizedDescription)
}
}
task.resume()
}
Below are two POST methods. Depending on if you want it synchronous (everything else waits until the post method is completed) or asynchronous (POST method runs in background, other methods run in parallel).
Methods
// POST data to url
func postDataAsynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ()) {
var URL: NSURL = NSURL(string: url)!
var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
request.HTTPMethod = "POST";
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()){
response, data, error in
var output: String!
if data != nil {
output = NSString(data: data, encoding: NSUTF8StringEncoding) as! String
}
completionHandler(responseString: output, error: error)
}
}
// Obtain the data
func postDataSynchronous(url: String, bodyData: String, completionHandler: (responseString: String!, error: NSError!) -> ())
{
let URL: NSURL = NSURL(string: url)!
var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
request.HTTPMethod = "POST"
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding);
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
var response: NSURLResponse?
var error: NSError?
// Send data
let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
var output: String! // Default to nil
if data != nil{
output = NSString(data: data!, encoding: NSUTF8StringEncoding) as! String
}
completionHandler(responseString: output, error: error)
}
Using them
You can then call (use) them like so:
postDataSynchronous(url, bodyData: bodyData) {
responseString, error in
if error != nil {
println("Error during post: \(error)")
return
}
else{
//Success
println(responseString)
userType = responseString // Set usertype based on server response
}
}
SWIFT 2.0
func postData(url: String, params: Dictionary<String, String>, completionHandler: (data: NSData?, response: NSURLResponse?, error: NSError?) -> ()) {
// Indicate download
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
let url = NSURL(string: url)!
// print("URL: \(url)")
let request = NSMutableURLRequest(URL: url)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// Verify downloading data is allowed
do {
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])
} catch let error as NSError {
print("Error in request post: \(error)")
request.HTTPBody = nil
} catch {
print("Catch all error: \(error)")
}
// Post the data
let task = session.dataTaskWithRequest(request) { data, response, error in
completionHandler(data: data, response: response, error: error)
// Stop download indication
UIApplication.sharedApplication().networkActivityIndicatorVisible = false // Stop download indication
}
task.resume()
}
guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { return }
let session = URLSession.shared
session.dataTask(with: url) { (data, response, error) in
if let response = response {
print(response)
}
if let data = data {
print(data)
do {
let json = try JSONSerialization.jsonObject(with: data, options: [])
print(json)
} catch {
print(error)
}
}
}.resume()
}
It's a get method.
This method invokes the http request.
String(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: &error)
Because Swift String has no init signature like this.
This method would be written somewhere in the project, as extension of String
It would be something like this
extension String{
init(contentsOfURL: NSURL, encoding: NSUTF8StringEncoding, inout error: NSError){
// load data from url
self = //parse data to string
}
}
The String(contentsOfUrl:encoding:error) initializer makes a GET request under the hood and returns the content as a string with the specified encoding.
One way to make a request would be to create an NSURLConnection and use NSMutablrURLRequest set the HTTP method the post. With the NSMutableURLRequest, you can create a NSURLConnection and start it immediately with a delegate or you can call NSURLConnection.sendSynchronousRequest or NSURLConnection.sendAsynchronousRequest to send the request.
let parameters = ["username": "#Bipin_kumar", "tweet": "HelloWorld"]
guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("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()
It's a post method.
GET Request
func getRequest(with url: URL, callback: #escaping (Any?) -> Swift.Void) -> Void {
let defaultConfigObject = URLSessionConfiguration.default
defaultConfigObject.timeoutIntervalForRequest = 30.0
defaultConfigObject.timeoutIntervalForResource = 60.0
let session = URLSession.init(configuration: defaultConfigObject, delegate: nil, delegateQueue: nil)
var urlRequest = URLRequest(url: url as URL)
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = "GET"
session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
guard let httpResponse: HTTPURLResponse = response as? HTTPURLResponse
else {
print("Error: did not receive data")
return
}
var response : (Any)? = nil
if httpResponse.statusCode == 200 {
print(httpResponse)
guard let responseData = data else {
print("Error: did not receive data")
return
}
do {
let responseData = try JSONSerialization.jsonObject(with: responseData, options: [JSONSerialization.ReadingOptions.allowFragments])
response = responseData
callback(response)
}
catch _ as NSError {
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
callback(responseString)
return
}
}
else {
print(httpResponse)
guard error == nil else {
print("error calling GET on /todos/1")
print(error ?? "error")
callback(response!)
return
}
}
}).resume()
}
POST REQUEST
//MARK: post request
func postRequest(with url:URL, postBody:String, callback: #escaping (Any?) -> Void) -> Void {
let defaultConfigObject = URLSessionConfiguration.default
defaultConfigObject.timeoutIntervalForRequest = 30.0
defaultConfigObject.timeoutIntervalForResource = 60.0
let session = URLSession.init(configuration: defaultConfigObject, delegate: nil, delegateQueue: nil)
let params: String! = postBody
var urlRequest = URLRequest(url: url as URL)
urlRequest.httpMethod = "POST"
let data = params.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))
urlRequest.httpBody = data
session.dataTask(with: urlRequest, completionHandler: { (data, urlResponse, error) in
guard let httpResponse:HTTPURLResponse = urlResponse as? HTTPURLResponse
else{
print("did not get any data")
return
}
var response : (Any)? = nil
if httpResponse.statusCode == 200 {
guard let responseData = data else {
print("Error: did not receive data")
return
}
do {
guard let responseData = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else {
print("error trying to convert data to JSON")
return
}
response = responseData
callback(response)
} catch _ as NSError {
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
callback(responseString)
return
}
}
else {
guard error == nil else {
print("error calling GET on /todos/1")
print(error ?? "error")
callback(nil)
return
}
}
}).resume()
}
Always try to check the HTTPURLResponse code

Resources