xcode Swift 4 将 POST 请求作为 x-www-form-urlencoded 发送
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48720925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift 4 send POST request as x-www-form-urlencoded
提问by Rexhin Hoxha
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.
我想向我的 php 7 服务器发送一个 POST 请求,它接受数据为application/x-www-form-urlencoded
. 我拥有的数据在 Struct 中,我想在提交时将该结构的每个属性作为参数获取。
This is the struct which handles my urlSession requests both GET and POST
XHR.swift
这是处理我的 urlSession 请求 GET 和 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()
}
}
This is the functions which sends a POST request to the server:
VideoViewModel.swift
这是向服务器发送 POST 请求的函数:
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))
}
}
}
And I call it like this:
我这样称呼它:
videoViewModel.login(username: "rexhin", password: "bonbon") { (result: VideoViewModel.Login) in
switch result {
case .failure(let error):
print("error")
case .success(let user):
print(user)
}
}
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:
从 PHP 我可以看到 POST 请求已成功提交,但是当我尝试username
通过执行获取该字段时,$_POST["username"]
我得到Undefined index:
Full code of the app can be seen here https://gitlab.com/rexhin/ios-kida.git
可以在此处查看应用程序的完整代码https://gitlab.com/rexhin/ios-kida.git
回答by OOPer
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.
您将结果User.archive(w: thing)
作为data
嵌入在请求正文中的形式传递,这可能永远不会起作用。通常,您的archive(w:)
和unarchive(d:)
永远不会产生任何有用的结果,您最好立即将其删除。
If you want to pass parameters where x-www-form-urlencoded
is needed, you need to create a URL-query-like string.
如果你想在x-www-form-urlencoded
需要的地方传递参数,你需要创建一个类似 URL 查询的字符串。
Try something like this:
尝试这样的事情:
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
//...
}
}
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.
上面的例子有点过于简化,当它们可以包含一些特殊字符时,您可能需要转义username
和/或password
在将其嵌入字符串之前。你可以在网上找到很多关于它的文章。
回答by Rizwan Ahmed
Quoting from this post
引自这篇文章
In PHP, a variable or array element which has never been set is different from one whose value is null; attempting to access such an unset value is a runtime error.
在 PHP 中,从未设置过的变量或数组元素与值为 null 的变量或数组元素不同;试图访问这样一个未设置的值是一个运行时错误。
The Undefined index error occurs when you try to access an unset variable or an array element. You should use function isset inorder to safely access the username param from the POST body. Try the below code in your PHP file.
当您尝试访问未设置的变量或数组元素时,会发生未定义索引错误。您应该使用函数 isset 以便从 POST 正文安全地访问用户名参数。在您的 PHP 文件中尝试以下代码。
if (isset($_POST["username"]))
{
$user= $_POST["username"];
echo 'Your Username is ' . $user;
}
else
{
$user = null;
echo "No user name found";
}
回答by Mohammad Muddasir
I used below code in swift 4
我在 swift 4 中使用了下面的代码
guard let url = URL(string: "http://192.168.88.129:81/authenticate") else {
return
}
let user1 = username.text!
let pass = passwordfield.text!
print(user1)
print(pass)
let data : Data = "username=\(user1)&password=\(pass)&grant_type=password".data(using: .utf8)!
var request : URLRequest = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type");
request.setValue(NSLocalizedString("lang", comment: ""), forHTTPHeaderField:"Accept-Language");
request.httpBody = data
print("one called")
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// vs let session = URLSession.shared
// make the request
let task = session.dataTask(with: request, completionHandler: {
(data, response, error) in
if let error = error
{
print(error)
}
else if let response = response {
print("her in resposne")
}else if let data = data
{
print("here in data")
print(data)
}
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)
// NSAssertionHandler(.success(todo))
} catch {
print("error trying to convert data to JSON")
//print(error)
// NSAssertionHandler(.failure(error))
}
}
})
task.resume()
}