POST with fast and API

I have a problem, when I try to send a POST request to my API on my server, I followed a lot of different tutorials, but it still does not work. I know that my problem is with the POST request, but I cannot solve it! So this is my code in Swift and my API in php: (and yes, I replaced xxxx with real identifiers in my code)

To summarize the server, get a request and, for example, if I manually entered a pseudo, it works, it really is a POST method that does not work. Server does not receive POST parameter

Quick code:

var request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/academy/test.php")!) var session = NSURLSession.sharedSession() request.HTTPMethod = "POST" var params = ["pseudo":"test"] as Dictionary<String, String> var err: NSError? request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err) request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.addValue("application/json", forHTTPHeaderField: "Accept") var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in println("Response: \(response)") var strData = NSString(data: data, encoding: NSUTF8StringEncoding) println("Body: \(strData)") var err: NSError? var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary // Did the JSONObjectWithData constructor return an error? If so, log the error to the console if(err != nil) { println(err!.localizedDescription) let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding) println("Error could not parse JSON: '\(jsonStr)'") } else { // The JSONObjectWithData constructor didn't return an error. But, we should still // check and make sure that json has a value using optional binding. if let parseJSON = json { // Okay, the parsedJSON is here, let get the value for 'success' out of it var success = parseJSON["success"] as? Int println("Succes: \(success)") } else { // Woa, okay the json object was nil, something went worng. Maybe the server isn't running? let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding) println("Error could not parse JSON: \(jsonStr)") } } }) task.resume()*/ 

PHP code:

 $BDD_hote = 'xxxxx'; $BDD_bd = 'xxxxx'; $BDD_utilisateur = 'xxxxx'; $BDD_mot_passe = 'xxxxx'; try{ $bdd = new PDO('mysql:host='.$BDD_hote.';dbname='.$BDD_bd, $BDD_utilisateur, $BDD_mot_passe); $bdd->exec("SET CHARACTER SET utf8"); $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); } catch(PDOException $e){ echo 'Erreur : '.$e->getMessage(); echo 'NΒ° : '.$e->getCode(); } $pseudo = addslashes($_POST["pseudo"]); $req = $bdd->query("SELECT * from users WHERE pseudo='$pseudo'"); $resultArray = array(); $donnees = $req->fetch(); echo json_encode($donnees); 

Thanks in advance:)

+6
source share
3 answers

Try the following:

  let myURL = NSURL(string: "http://localhost:8888/academy/test.php")! let request = NSMutableURLRequest(URL: myURL) request.HTTPMethod = "POST" request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") request.setValue("application/json", forHTTPHeaderField: "Accept") let bodyStr:String = "pseudo=test" request.HTTPBody = bodyStr.dataUsingEncoding(NSUTF8StringEncoding) let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in // Your completion handler code here } task.resume() 

You must encode your data using UTF8 string encoding. If you need to set several pairs of fields and parameters for the request body, you can change the body line, for example, "pseudo = test & language = swift". In fact, I usually create an extension for NSMutableURLRequest and add a method that takes the dictionary as a parameter and sets the contents of this map (dictionary) as HTTPBody using the correct encoding. This might work for you:

  extension NSMutableURLRequest { func setBodyContent(contentMap: Dictionary<String, String>) { var firstOneAdded = false let contentKeys:Array<String> = Array(contentMap.keys) for contentKey in contentKeys { if(!firstOneAdded) { contentBodyAsString += contentKey + "=" + contentMap[contentKey]! firstOneAdded = true } else { contentBodyAsString += "&" + contentKey + "=" + contentMap[contentKey]! } } contentBodyAsString = contentBodyAsString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! self.HTTPBody = contentBodyAsString.dataUsingEncoding(NSUTF8StringEncoding) } } 

And you can use it like:

 request.setBodyContent(params) 

Hope this helps you!

+11
source

As others have pointed out, the request encoding is not entirely correct. Your server code does not expect a JSON request, but uses the $_POST variables (which means that the request must have Content-Type of application/x-www-form-urlencoded ). So what you have to create. For example, in Swift 3 and later:

 var request = URLRequest(url: url) request.httpMethod = "POST" let parameters = ["somekey" : "valueforkey"] request.setContent(with: parameters) let task = session.dataTask(with: request) { data, response, error in guard let data = data, error == nil else { print(error ?? "Unknown error") return } // your response parsing code here } task.resume() 

A dictionary of the form ["key1": "foo", "key2" : "bar"] httpBody in the httpBody and httpBody filled httpBody something that looks like key1=foo&key2=bar . If you do this, the server will be able to parse $_POST from the request.

 extension URLRequest { /// Set body and header for x-www-form-urlencoded request /// /// - Parameter parameters: Simple string dictionary of parameters to be encoded in body of request mutating func setContent(with parameters: [String: String]) { setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") let array = parameters.map { entry -> String in let key = entry.key.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)! let value = entry.value.addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed)! return key + "=" + value } httpBody = array.joined(separator: "&").data(using: .utf8)! } } 

Note that this also percent-encodes the values ​​(and, just in case, the keys), which is critical. While others advise using addingPercentEncoding with .urlQueryAllowed , unfortunately this will not do the job, as it will allow some reserved characters (especially + ) to go through without saving. Most web services interpret + as a space according to the x-www-form-urlencoded specification . So, adapting the approach adopted by Alamofire, I define a character set that will encode values ​​with different delimiters:

 extension CharacterSet { /// Returns the character set for characters allowed in the individual parameters within a query URL component. /// /// The query component of a URL is the component immediately following a question mark (?). /// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query /// component is `key1=value1`. The individual parameters of that query would be the key `key1` /// and its associated value `value1`. /// /// According to RFC 3986, the set of unreserved characters includes /// /// `ALPHA / DIGIT / "-" / "." / "_" / "~"` /// /// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters /// for the sake of compatibility with some erroneous implementations, so this routine also allows those /// to pass unescaped. static var urlQueryValueAllowed: CharacterSet = { let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4 let subDelimitersToEncode = "!$&'()*+,;=" var allowed = CharacterSet.urlQueryAllowed allowed.remove(charactersIn: generalDelimitersToEncode + subDelimitersToEncode) return allowed }() } 

For Swift 2, see the previous version of this answer .

+15
source

The following php code is for receiving the application/url+encode message with the message encoding. please refer https://en.wikipedia.org/wiki/Percent-encoding

 $_POST["pseudo"] 

and your fast code sent JSON string data. They are incompatible.

If you do not want to change the php code, in Swift you must send a message in the format url-encode, li:

// UPDATED with fixes from @Rob

  var params = ["param1":"value1", "papam2": "value 2"] var body = "" for (key, value) in params { body = body.stringByAppendingString(key) body = body.stringByAppendingString("=") body = body.stringByAppendingString(value.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!) body = body.stringByAppendingString("&") } body = body.substringToIndex(advance(body.startIndex, countElements(body)-1)) // remove the last "&" request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) 
+1
source

Source: https://habr.com/ru/post/981170/


All Articles