phpswiftrequesthttp-post

Post Request from Swift to PHP server is sent in the key of $_POST


Made a basic post request in Swift and the values are received in the key of the $_POST array.

Swift Code:

        struct TestResponse: Codable{
           let test: String
        }
   
       func postData<T:Codable>( parameters: T, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
        
        let urlString = "http://example.com"
        
        var request = URLRequest(url: URL(string: urlString)! )
        request.addValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With")
        request.setValue("application/json, text/javascript, /; q=0.01", forHTTPHeaderField: "Accept")
        request.httpMethod = "POST"
        request.httpBody = try! JSONEncoder().encode(parameters)
        URLSession.shared.dataTask(with: request) { data, response, error in
            completion(data, response, error)
        }.resume()
    }

    //sent variable as parameters
    let test = TestResponse(test: "string with space")

And what I get is:

[{"test":"string_with_space"}] =>

Looks like the whole serialized JSON string in the key of the $_POST array, and an empty value for it. I am new to this. I am sure I am missing something like a header.

I am trying to have the request be distributed in the PHP post request as the name of the variable in the key of the post and the value of the variable in the $_POST value.


Solution

  • So the solution that I found to this is treating the request body like a string, and setting the content disposition for each item you want to send in your post request:

    func createMultipartBody(boundary:String, parameters: [String: String], images: [UIImage]) -> Data {
        let body = NSMutableData()
        
        // Add parameters
        for (key, value) in parameters {
            body.appendString("--\(boundary)\r\n")
            body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
            body.appendString("\(value)\r\n")
        }
        
        body.appendString("--\(boundary)--\r\n")
        
        return body as Data
    }
    

    This is a function that creates the post request for me:

    func postDataRequest( parameters: [String:String], action: String, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
        let boundary = "Boundary-\(UUID().uuidString)"
        let body = createMultipartBody(boundary:boundary, parameters: parameters)
    
        guard let baseURL = UserDefaults.standard.string(forKey: "baseURL") else { return }
        guard let url = URL(string: "\(baseURL)/\(action)") else { return }
        var request = URLRequest(url: url)
        
        request.httpMethod = "POST"
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        request.setValue(String(body.count), forHTTPHeaderField: "Content-Length")
        request.addValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With")
        request.httpBody = body
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            completion(data, response, error)
        }.resume()
    }
    

    For sending images you will have to set the content-type also based on the image mimetype, and append the image data. This example is for jpeg and image is a UIImage object:

    if let imageData = image.jpegData(compressionQuality: 0.7) {
        let filename = "\(UUID().uuidString).jpg"
        let mimetype = "image/jpeg"
    
        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"images[]\"; filename=\"\(filename)\"\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.append(imageData)
        body.appendString("\r\n")
    }