2015-01-18 15 views
6

Tôi gặp sự cố khi tôi gửi yêu cầu POST tới API của tôi trên máy chủ của mình, tôi đã theo nhiều hướng dẫn khác nhau nhưng vẫn không hoạt động. Tôi biết vấn đề của tôi là với yêu cầu POST nhưng tôi không thể giải quyết nó! Vì vậy, đây là mã của tôi trong Swift và API của tôi bằng php: (và có, tôi đã thay thế xxxx bằng các ID thực trong mã của tôi)POST bằng swift và API

Để tổng hợp máy chủ nhận yêu cầu và ví dụ nếu tôi nhập thủ công pseudo nó hoạt động, đó là thực sự là phương thức POST người không hoạt động .. các máy chủ không nhận tham số POST

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

Cảm ơn trước :)

+1

Vui lòng cung cấp thêm một chút chi tiết về "không hoạt động"? Từ đầu và tiếp tục, bước nào không cho bạn kết quả mong đợi. Máy chủ có nhận được yêu cầu không? – kcome

+0

Vì vậy, máy chủ nhận được yêu cầu và ví dụ nếu tôi nhập thủ công một giả mạo, nó thực sự là phương thức POST không hoạt động .. Máy chủ không nhận được thông số POST – sebasthug

+0

Bằng cách này, điểm nhỏ, nhưng hãy xem tài liệu ['addSlashes'] (http://php.net/manual/en/function.addslashes.php) khuyên bạn sử dụng [' mysqli_real_escape_string'] (http://php.net/manual/en/mysqli .real-escape-string.php), thay vào đó. – Rob

Trả lời

11

Hãy thử điều này :

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

Bạn phải mã hóa dữ liệu bằng cách sử dụng mã hóa chuỗi UTF8. Nếu bạn cần đặt nhiều trường & cặp giá trị cho phần thân yêu cầu, bạn có thể thay đổi chuỗi nội dung, ví dụ: "pseudo = test & language = swift". Trong thực tế, tôi thường tạo một phần mở rộng cho NSMutableURLRequest và thêm một phương thức lấy từ điển làm tham số và đặt nội dung của bản đồ này (từ điển) thành HTTPBody bằng cách sử dụng mã hóa chính xác. Điều này có thể làm việc cho bạn:

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

Và bạn có thể sử dụng như:

request.setBodyContent(params) 

Tôi hy vọng điều này sẽ giúp bạn!

+1

Cảm ơn bạn rất nhiều vì điều này! =) – CodeMonkey

1

mã php sau đây để nhận application/url+encode tin nhắn được mã hóa. vui lòng tham khảo https://en.wikipedia.org/wiki/Percent-encoding

$_POST["pseudo"] 

và mã nhanh của bạn đang gửi dữ liệu chuỗi được mã hóa JSON. Chúng không tương thích.

Nếu bạn không muốn thay đổi mã php, trong Swift bạn nên gửi tin nhắn định dạng url-mã hóa, li:

// CẬP NHẬT với sự điều chỉnh từ @ 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

Tôi đã thử nhưng nó không hoạt động:/Nhưng tôi có thể thay đổi mọi thứ (trong PHP hoặc Swift) không có vấn đề gì :) – sebasthug

+0

Tôi xin lỗi tôi không có chuyên gia về PHP, vì vậy từ những gì tôi hiểu được mã PHP của bạn, vấn đề là do định dạng dữ liệu khác nhau giữa bên gửi và bên nhận. – kcome

+0

Đừng quên thay đổi 'Content-Type' trong người gửi/Swift, thiết lập này:' request.addValue ("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 'không phải là json gốc một. – kcome

15

Như những người khác đã chỉ ra, việc mã hóa yêu cầu không hoàn toàn đúng. Mã máy chủ của bạn không mong đợi yêu cầu JSON, mà đúng hơn là sử dụng các biến số $_POST (có nghĩa là yêu cầu phải có Content-Type của application/x-www-form-urlencoded). Vì vậy, đó là những gì bạn nên tạo. Ví dụ trong Swift 3 và sau:

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

Phương pháp setContent sẽ mất một cuốn từ điển có dạng ["key1": "foo", "key2" : "bar"] và cư trú trong httpBody với cái gì đó trông giống như key1=foo&key2=bar. Nếu bạn làm như vậy, máy chủ sẽ có thể phân tích cú pháp số $_POST từ yêu cầu.

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

Lưu ý, điều này cũng mã hóa phần trăm các giá trị (và, chỉ trong trường hợp, các phím) quá quan trọng. Trong khi những người khác đã khuyên sử dụng addingPercentEncoding với .urlQueryAllowed, thật đáng buồn là sẽ không thực hiện công việc, vì nó sẽ cho phép một số ký tự dành riêng (đặc biệt là +) vượt qua không thoát. Hầu hết các dịch vụ web sẽ giải thích + là không gian, phù hợp với the x-www-form-urlencoded spec. Vì vậy, thích nghi một cách tiếp cận được thông qua bởi Alamofire, tôi xác định một bộ ký tự này sẽ mã hóa các giá trị với delimiters khác nhau:

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

Đối Swift 2 rendition, xem previous revision of this answer.

+1

Tôi nhận được một số tham số có ký tự '+', liên tục thất bại .... cảm ơn cuối cùng đã nhận nó :) –

+0

Cảm ơn người đàn ông .. làm việc tốt – Sandu

Các vấn đề liên quan