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