2015-01-18 2 views
6

У меня проблема при попытке отправить POST-запрос на мой API на моем сервере, я следил за множеством разных учебников, но он по-прежнему не работает. Я знаю, что моя проблема связана с запросом POST, но я не могу ее решить! Итак, это мой код в Swift и мой API в php: (и да, я заменил xxxx на реальные идентификаторы в моем коде)POST с быстрым и API

Подводя итог серверу, получите запрос и, например, псевдо это работает, это действительно метод POST, который не работает .. сервер не принимает параметр POST

Swift код:

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); 

Спасибо заранее :)

+1

Просьба немного подробнее о «не работает»? С самого начала и дальше, какой шаг не дает вам ожидаемого результата. Сервер вообще не получил запрос? – kcome

+0

Таким образом, сервер получает запрос и, например, если я вручную ввел псевдо, он работает. Это действительно метод POST, который не работает. Сервер не получает параметр POST – sebasthug

+0

Кстати, второстепенную точку, но см. документацию '' addSlashes '' (http://php.net/manual/en/function.addslashes.php), которая советует вам использовать ['mysqli_real_escape_string'] (http://php.net/manual/en/mysqli .real-escape-string.php). – Rob

ответ

11

Попробуйте это :

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) 

Я надеюсь, что это поможет вам!

+1

Большое спасибо за это! =) – CodeMonkey

1

следующий код php предназначен для получения application/url+encode закодированного сообщения сообщения. обратитесь https://en.wikipedia.org/wiki/Percent-encoding

$_POST["pseudo"] 

и ваш код быстры посылал JSON закодированные строки данных. Они несовместимы.

Если вы не хотите, чтобы изменить код PHP в Swift вы должны отправить URL закодировать сообщение в формате, литий:

// ОБНОВЛЕНО с поправками от @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) 
+0

Я пробовал, но он не работает:/Но я могу все изменить (в PHP или Swift) нет никаких проблем :) – sebasthug

+0

Прошу прощения, я не эксперт в PHP, поэтому из того, что я понимаю в ваш PHP-код, проблема вызвана различным форматом данных между передающей и принимающей стороной. – kcome

+0

Не забудьте изменить 'Content-Type' в sender/Swift, установите это:' request.addValue («application/x-www-form-urlencoded», forHTTPHeaderField: «Content-Type») 'не оригинальный json один. – kcome

15

Как указывали другие, кодировка запроса не совсем правильная. Ваш код сервера не ожидает запроса JSON, а использует $_POST переменные (это означает, что запрос должен иметь Content-Type из application/x-www-form-urlencoded). Вот что вы должны создать. Например, в Swift 3 и более поздних версий:

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() 

Метод setContent бы словарь формы ["key1": "foo", "key2" : "bar"] и заполнить httpBody с чем-то, что выглядит как key1=foo&key2=bar. Если вы это сделаете, сервер сможет разобрать $_POST с запросом.

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)! 
    } 
} 

Заметим, что это также процентов кодирует значения (и, только в том случае, ключи, тоже), что имеет решающее значение. В то время как другие советовали использовать addingPercentEncoding с .urlQueryAllowed, к сожалению, это не сработает, так как это позволит некоторым зарезервированным символам (особенно +) проходить без сохранения. Большинство веб-сервисов интерпретируют + как пространство, соответствующее the x-www-form-urlencoded spec. Таким образом, адаптируя подход, принятый Alamofire, я определяю набор символов, который будет кодировать значения с различными разделителями:

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 
    }() 
} 

Для Swift 2 исполнения, см previous revision of this answer.

+1

У меня есть какой-то параметр с символом «+», постоянно сбой .... спасибо, наконец, получил его :) –

+0

Спасибо, человек ... отлично работает – Sandu

Смежные вопросы