У меня проблема, когда я пытаюсь отправить POST-запрос на свой API на моем сервере, я следил за множеством различных учебников, но он все равно не работает. Я знаю, что моя проблема связана с запросом POST, но я не могу его решить! Итак, это мой код в Swift и мой API в php: (и да, я заменил xxxx реальными идентификаторами в моем коде)
Подводя итог серверу, получите запрос и, например, если я вручную ввел псевдо, он работает. Это действительно метод POST, который не работает. Сервер не получает параметр POST
Быстрый код:
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's 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:
$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);
Спасибо заранее 🙂
Попробуй это:
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()
Вы должны кодировать свои данные с помощью строковой кодировки UTF8. Если вам нужно установить несколько пар полей и значений для тела запроса, вы можете изменить строку тела, например, «pseudo = test & language = swift». Фактически, я обычно создаю расширение для NSMutableURLRequest и добавляю метод, который принимает словарь как параметр и устанавливает содержимое этой карты (словаря) в качестве HTTPBody, используя правильную кодировку. Это может сработать для вас:
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) } }
И вы можете использовать это как:
request.setBodyContent(params)
Я надеюсь, это поможет вам!
Как указывали другие, кодировка запроса не совсем правильная. Ваш код сервера не ожидает запроса JSON, а использует переменные $_POST
(это означает, что запрос должен иметь Content-Type
of application/x-www-form-urlencoded
). Вот что вы должны создать. В Swift 3:
var request = URLRequest(url: url) request.httpMethod = "POST" let parameters = ["somekey" : "valueforkey"] request.setBodyContent(parameters) request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") request.addValue("application/json", forHTTPHeaderField: "Accept") let task = session.dataTask(with: request) { data, response, error in guard let data = data, error == nil else { print("\(error?.localizedDescription ?? "Unknown error")") return } // your response parsing code here } task.resume()
Метод setBodyContent
будет принимать словарь формы ["key1": "foo", "key2" : "bar"]
и заполнять HTTPBody
чем-то, что выглядит как key1=foo&key2=bar
. Если вы это сделаете, сервер сможет проанализировать $_POST
из запроса.
extension URLRequest { /// Populate the HTTPBody of `application/x-www-form-urlencoded` request /// /// - parameter parameters: A dictionary of keys and values to be added to the request mutating func setBodyContent(_ parameters: [String : String]) { let parameterArray = parameters.map { (key, value) -> String in return "\(key.addingPercentEncodingForQuery()!)=\(value.addingPercentEncodingForQuery()!)" } httpBody = parameterArray.joined(separator: "&").data(using: .utf8) } }
Обратите внимание, что это также процент-кодирует значения, что является критическим. В то время как другие советуют использовать addingPercentEncoding
, к сожалению, это не будет выполнять задание, так как это позволит некоторым зарезервированным символам проходить без сохранения. Примечательно, что в маловероятной ситуации, когда значения словаря параметров параметров запроса содержали символ &
или +
, он позволял им пропускать unescaped (а символ &
будет неправильно интерпретирован как завершение значения, а символ +
будет интерпретирован как пробел). Таким образом, вам нужно выполнить свой собственный процент, чтобы убедиться, что только узко определенный набор незаслуженных символов оставлен без привязки. Вы могли бы сделать что-то вроде:
extension String { /// Percent escape value to be added to a HTTP request /// /// This percent-escapes all characters besides the alphanumeric character set and "-", ".", "_", and "*". /// This will also replace spaces with the "+" character as outlined in the application/x-www-form-urlencoded spec: /// /// http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm /// /// - returns: Return percent escaped string. func addingPercentEncodingForQuery() -> String? { let allowed = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._* ") return addingPercentEncoding(withAllowedCharacters: allowed)?.replacingOccurrences(of: " ", with: "+") } }
Кроме того, вы можете создать набор символов допустимых символов, начиная с .urlQueryAllowed
, но вам все равно придется удалить несколько символов, поскольку в противном случае это может привести к тому, что некоторые символы пройдут без сохранения (например, +
). См. https://stackoverflow.com/a/35912606/1271826 .
Для версии Swift 2 см. Предыдущую ревизию этого ответа .
следующий код php предназначен для получения сообщения с application/url+encode
encoded posted. см. https://en.wikipedia.org/wiki/Percent-encoding
$_POST["pseudo"]
и ваш быстрый код отправлял строковые данные, закодированные JSON
. Они несовместимы.
Если вы не хотите изменять php-код, в Swift вы должны отправить сообщение формата url-encode, li:
// ОБНОВЛЕНО с исправлениями от @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)