I am using this code below to send a HTTP request to my PHP API
static func submitNumber(parameters: [String: Any]){
print("parameters", parameters)
guard let url = URL(string: Constants.phoneVerifyUrl) else {
print("URL not found")
return
}
let datas = try! JSONSerialization.data(withJSONObject: parameters, options: [])
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = datas
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
let urlSession = URLSession.shared.dataTask(with: request) { data, _, error in
if error != nil {
print("error", error?.localizedDescription ?? "")
return
}
do {
if let data = data {
print("data", data)
let decodedData = try JSONDecoder().decode(DataModels.self, from: data)
DispatchQueue.main.async {
let noError = decodedData.noError
let dataStr = decodedData.dataStr
print("noError", noError)
print("dataStr", dataStr)
}
} else {
print("No Data received")
}
} catch let JsonError {
print("JSON error", JsonError.localizedDescription)
}
}
urlSession.resume()
}
And then in my PHP API, I try to receive the data like this
<?php
if(isset($_POST)){
$phoneNumber = $_POST['phoneNumber'];
//Run Code here
}
?>
When I do
print("parameters", parameters)
This is what I get (As expected)
parameters ["phoneNumber": "1234567890"]
But then, for a reason I don't know, the code in my PHP API is not executing. The PHP code is perfectly working because I use the same API for my Android app and it works fine, so I know the issue is not from my PHP API
And when I also do this print("data", data) I get a random number like this data 8402 bytes
For me, I believe I'm not passing the parameters in the right way to my API, Since I'm new to Swift, I don't know how it's done
And for my URL string Constants.phoneVerifyUrl, it's okay
Please note: I don't want to temper with my PHP API as I also use it for my Android app. So I need only to fix my Swift code
I found an answer from to create post body request data using below code.
var jsonData:Data?
do {
jsonData = try JSONSerialization.data(withJSONObject: dic, options: .prettyPrinted)
} catch {
print(error.localizedDescription)
}
and then create the request like this.
let url = URL(string: "https://blah.com/server/dudes/decide/this")!
var request = URLRequest(url: url)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
request.httpMethod = "POST"
request.httpBody = jsonData
Okay... My first answer was wrong, but I've got it figured out.
First I removed this lines
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
And replaced it with this
request.addValue("application/json", forHTTPHeaderField: "Accept")
Then I changed my Data parameters dictionary from JSON to String
var datas = parameters.toQueryString.data(using: .utf8)!
Below is the Dictionary extension of toQueryString
extension Dictionary {
var toQueryString: String? {
return self.reduce("") { "\($0!)\($1.0)=\($1.1)&" }
}
}
Related
I have the following Swift 5 function that calls a PHP script on my server:
func getJSONdata(fileName:String, completion: (_ json:JSON)->()) {
let session = URLSession(configuration: .ephemeral)
var jsonData = JSON()
let myUrl = URL(string: DATABASE_PATH + fileName + "/query.php?queryAll");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
DispatchQueue.main.async {
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
print("\(error!.localizedDescription)")
return
}
// Get data
jsonData = try! JSON(data: data!)
// print(jsonData)
}
task.resume()
}// ./ dispatch aync
completion(jsonData)
}
This function is hosted in a separate Swift file, now in my ViewController.swift I call that function as follows:
getJSONdata(fileName: "Users") { (jsonData) in
print("\(jsonData)")
}
In this case, I'm getting an empty array in my Xcode console, instead, if I uncomment the // print(jsonData) that's inside my getJSONdata() function, the console prints out my JSON data.
Obviously I'm doing something wrong in my getJSONdata() function because I cannot retrieve data by calling in ViewController.swift.
Where is the error in my function?
Try the below code. Maybe it will help you.
func getJSONdata(fileName:String, completion:#escaping (_ json:JSON)->()) {
let session = URLSession(configuration: .ephemeral)
var jsonData = JSON()
let myUrl = URL(string: DATABASE_PATH + fileName + "/query.php?queryAll");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
DispatchQueue.main.async {
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
print("\(error!.localizedDescription)")
completion(nil)
}
// Get data
jsonData = try! JSON(data: data!)
// print(jsonData)
completion(jsonData)
}
task.resume()
}
}
I've found a solution, I don't know why but if I add #escaping to my function declaration, it works fine.
I also had to move completion(jsonData) below jsonData = try! JSON(data: data!), as suggested by #chirag90.
So, here's the complete function:
func getJSONdata(fileName:String, completion: #escaping (_ json:JSON?) -> Void) {
let session = URLSession(configuration: .ephemeral)
var jsonData = JSON()
let myUrl = URL(string: DATABASE_PATH + fileName + "/query.php?queryAll");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
DispatchQueue.main.async {
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
self.simpleAlert("\(error!.localizedDescription)")
return
}
// Get data
jsonData = try! JSON(data: data!)
completion(jsonData)
}
task.resume()
}// ./ dispatch aync
}
The code I've posted here is a shortened versions with just the essentials to the issue. When put through rigorous error testing, it appears that there are no issues either within the request, within the server, or within the return code, except for the fact that the response from the server says "Function": null instead of "Function": "addUser" as it should. Is there something I'm doing wrong on either end? It just seems to not be recognizing the posted variables, but I've used this code numerous times in other apps and servers and it seems to be failing here for some reason I cannot see. Thank you for any assistance.
Here is my PHP on the server:
<?php
$t = $_POST["function"];
$do = array("Success"=>true, "Function"=> $t);
echo json_encode($do);
?>
Here is the swift I'm using to make the request:
let params = ["function": "addUser"] as [String: AnyObject]?
fetchData("https://pdt.pitchprogress.net/SamplePHP.php", token: nil, parameters: params, method: "POST", onCompletion: { (success, data) -> Void in
if success {
do {
let json = try JSON(data: data!)
if json["Success"].boolValue == true {
print("success!")
print(json.description)
print(json["Function"].stringValue)
}
}
}
})
func fetchData(_ feed:String,token:String? = nil,parameters:[String:AnyObject]? = nil,method:String? = nil, onCompletion:#escaping (_ success:Bool,_ data:Data?)->Void){
DispatchQueue.main.async {
if let unwrapped_url = URL(string: feed){
let request = NSMutableURLRequest(url: unwrapped_url)
if let parm = parameters {
if let data = (try? JSONSerialization.data(withJSONObject: parm, options:[])) as Data? {
request.httpBody = data
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("\(data.count)", forHTTPHeaderField: "Content-Length")
}
}
if let unwrapped_method = method {
request.httpMethod = unwrapped_method
}
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.timeoutIntervalForRequest = 15.0
let session = URLSession(configuration: sessionConfiguration)
let taskGetCategories = session.dataTask(with: request as URLRequest, completionHandler: { (responseData, response, error) -> Void in
let statusCode = (response as! HTTPURLResponse?)?.statusCode
//println("Status Code: \(statusCode), error: \(error)")
if error != nil || (statusCode != 200 && statusCode != 201 && statusCode != 202){
onCompletion(false, nil)
} else {
onCompletion(true, responseData)
}
})
taskGetCategories.resume()
}
}
}
This is because you are sending the params as JSON while your API requires params as form data.
This code sends the params as simple form post and this retrieved successful response.
var request = URLRequest(url: URL(string: "http://app123.freeiz.com/Apis/samples/api4.php")!)
request.httpMethod = "POST"
var postString = ""
postString.append("function=value") // replace 'function' with your paramname and 'value' with your value'
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
// check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
// check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
if let unWrappedResponseString = responseString{
print(unWrappedResponseString)
}
}
task.resume()
I had once made a small wrapper for sending simple form data, If i find it I will update the answer with that. Till then you can try with this. Let me know how it goes..
Looks like your key is different use "function" instead of using "Function"
I am trying to send data via POST to a server in Swift 2.1, however, the server never appears to receive any of the data.
Swift:
let url = NSURL(string: "http://www.myserver.com/test.php");
let request = NSMutableURLRequest(URL:url!)
request.HTTPMethod = "POST";
let postString = "firstName=TestName1&lastName=TestName2";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let session = NSURLSession.sharedSession();
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
let urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding) as NSString!
print("Data: \(urlContent)");
});
task.resume();
PHP:
<?php
// Read request parameters
$firstName= $_REQUEST["firstName"];
$lastName = $_REQUEST["lastName"];// Store values in an array
$returnValue = array(“firstName”=>$firstName, “lastName”=>$lastName);
// Send back request in JSON format
echo json_encode($returnValue); ?>
Returns:
Data: {"firstName":null,"lastName":null}
I have canvased the web in an attempt to solve this problem, however, most of the solutions are out of date as they do not conform to the deprecations and changes brought with Swift 2.
Any ideas?
By removing the following lines of code, I got the data to return correctly:
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
Hi I am trying to connect my iOS app to my PHP API.
I am sending JSON POST to my PHP API but I am getting an empty array as Output.
My Swift Code
#IBAction func JSONButtonAction(sender: AnyObject) {
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration)
var usr = "dsdd"
var pwdCode = "dsds"
var image : UIImage = clickedPhotoView.image!
var imageData = UIImagePNGRepresentation(image)
let base64String = imageData.base64EncodedStringWithOptions(.allZeros)
let params:[String: AnyObject] = [
"email" : usr,
"image" : base64String ]
let url = NSURL(string:"http://localhost/app/")
let request = NSMutableURLRequest(URL: url!)
let boundaryConstant = "Boundary-7MA4YWxkTLLu0UIW"; // This should be auto-generated.
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.allZeros, error: &err)
let task = session.dataTaskWithRequest(request) {
data, response, error in
// println("response = \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("\(responseString)")
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode != 200 {
println("response was not 200: \(response)")
return
}
}
if (error != nil) {
println("error submitting request: \(error)")
return
}
// handle the data of the successful response here
var result = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as? NSDictionary
//println(result)
}
task.resume()
}
PHP Code
print_r($_POST);
Output is
array(
)
But when I use
$data = json_decode(file_get_contents('php://input'), true);
It works fine
I dont know why $_POST is not working.
If your intent is actually to send a string, then you should change the content-type:
request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
Tested your exact code with this modification on my tests server:
Otherwise, check #kekub's comment.
I simply want to POST some data from Swift to a PHP script. I've Googled for about two days on this and everyone seems to be doing the same thing, but it's not working for me. I have this Swift code triggered on viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
let request = NSMutableURLRequest(URL: NSURL(string: "http://mywebsite.com/scriptToHandlePOST.php")!) // it forces me to add the !
request.HTTPMethod = "POST"
var err: NSError?
let postString = "var1=value1&var2=value2".dataUsingEncoding(NSUTF8StringEncoding)
var postLength:NSString = String( postString!.length )
request.HTTPBody = postString
request.setValue(postLength, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error -> Void in
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println(response) // this returns a 200
println(strData!) // this returns an empty array of the $_POST variable
}
task.resume() // this is needed to start the task
}
My PHP script is simply just trying to get $_POST data:
<?php
print_r($_POST);
?>
Since the $_POST returns an empty array I suspect the POST request is never making it to my website. Do you see anything wrong in the code?