Swift 4将POST请求发送为x-www-form-urlencoded [英] Swift 4 send POST request as x-www-form-urlencoded

查看:286
本文介绍了Swift 4将POST请求发送为x-www-form-urlencoded的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想向我的php 7服务器发送一个POST请求,该服务器接受数据为application/x-www-form-urlencoded.我拥有的数据在Struct内部,我想在提交该结构时获取此结构的每个属性作为参数.

I want to send a POST request to my php 7 server which accepts data as application/x-www-form-urlencoded. The data I have is inside a Struct and I want to get every property of this struct as a parameter when I submit it.

这是处理我的urlSession请求GET和POST的结构 XHR.swift

This is the struct which handles my urlSession requests both GET and POST XHR.swift

struct XHR {

    enum Result<T> {
        case success(T)
        case failure(Error)
    }

    func urlSession<T>(method: String? = nil, file: String, data: Data? = nil, completionHandler: @escaping (Result<T>) -> Void) where T: Codable {

        let file = file.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!

        // Set up the URL request
        guard let url = URL.init(string: file) else {
            print("Error: cannot create URL")
            return
        }

        var urlRequest = URLRequest(url: url)

        if method == "POST" {
            urlRequest.httpMethod = "POST";
            urlRequest.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
            urlRequest.httpBody = data
            print(urlRequest.httpBody)
        }

        // set up the session
        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)
        // vs let session = URLSession.shared

        // make the request
        let task = session.dataTask(with: urlRequest, completionHandler: {
            (data, response, error) in

            DispatchQueue.main.async { // Correct

                guard let responseData = data else {
                    print("Error: did not receive data")
                    return
                }

                let decoder = JSONDecoder()
                print(String(data: responseData, encoding: .utf8))
                do {
                    let todo = try decoder.decode(T.self, from: responseData)
                    completionHandler(.success(todo))
                } catch {
                    print("error trying to convert data to JSON")
                    //print(error)
                    completionHandler(.failure(error))
                }
            }
        })
        task.resume()
    }

}

这是将POST请求发送到服务器的功能: VideoViewModel.swift

This is the functions which sends a POST request to the server: VideoViewModel.swift

struct User: Codable {
    let username: String
    let password: String

    static func archive(w:User) -> Data {
        var fw = w
        return Data(bytes: &fw, count: MemoryLayout<User>.stride)
    }

    static func unarchive(d:Data) -> User {
        guard d.count == MemoryLayout<User>.stride else {
            fatalError("BOOM!")
        }

        var w:User?
        d.withUnsafeBytes({(bytes: UnsafePointer<User>)->Void in
            w = UnsafePointer<User>(bytes).pointee
        })
        return w!
    }
}

enum Login {
    case success(User)
    case failure(Error)
}

func login(username: String, password: String, completionHandler: @escaping (Login) -> Void) {
    let thing = User(username: username, password: password)
    let dataThing = User.archive(w: thing)

    xhr.urlSession(method: "POST", file: "https://kida.al/login_register/", data: dataThing) { (result: XHR.Result<User>) in
        switch result {
        case .failure(let error):
            completionHandler(.failure(error))
        case .success(let user):
            //let convertedThing = User.unarchive(d: user)
            completionHandler(.success(user))
        }
    }
}

我这样称呼它:

videoViewModel.login(username: "rexhin", password: "bonbon") { (result: VideoViewModel.Login) in
    switch result {
    case .failure(let error):
        print("error")

    case .success(let user):
        print(user)
    }
}

从PHP可以看到POST请求已成功提交,但是当我尝试通过执行$_POST["username"]来获取username字段时,我得到了Undefined index:

From PHP I can see that a POST request is submitted successfully but when I try to get the username field by doing $_POST["username"] I get Undefined index:

可以在此处查看该应用的完整代码 https://gitlab.com/rexhin/ios-kida.git

Full code of the app can be seen here https://gitlab.com/rexhin/ios-kida.git

推荐答案

您正在传递User.archive(w: thing)的结果作为嵌入在请求正文中的data,这可能永远无法工作.通常,您的archive(w:)unarchive(d:)永远不会产生任何有用的结果,您最好立即删除它们.

You are passing the result of User.archive(w: thing) as the data embedded in the request body, which may never work. Generally, your archive(w:) and unarchive(d:) would never generate any useful results and you should better remove them immediately.

如果要在需要x-www-form-urlencoded的地方传递参数,则需要创建类似URL查询的字符串.

If you want to pass parameters where x-www-form-urlencoded is needed, you need to create a URL-query-like string.

尝试这样的事情:

func login(username: String, password: String, completionHandler: @escaping (Login) -> Void) {
    let dataThing = "username=\(username)&password=\(password)".data(using: .utf8)

    xhr.urlSession(method: "POST", file: "https://kida.al/login_register/", data: dataThing) { (result: XHR.Result<User>) in
        //...
    }
}

上面的示例有点过于简化,您可能需要先将username和/或password转义,然后才能将它们嵌入字符串中,因为它们可以包含一些特殊字符.您可以在网络上找到许多有关它的文章.

The example above is a little bit too simplified, that you may need to escape username and/or password before embedding it in a string, when they can contain some special characters. You can find many articles on the web about it.

这篇关于Swift 4将POST请求发送为x-www-form-urlencoded的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆