Để thực hiện HTTP request trong iOS, chúng ta sử dụng URLSession với dataTask. Bài viết này hướng dẫn tạo POST request hoàn chỉnh với JSON.
Các bước tạo POST Request
1. Tạo URLSessionConfiguration và Session
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration)
2. Tạo URLRequest với method POST
let urlString = "https://api.example.com/endpoint"
guard let url = URL(string: urlString) else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// Body JSON
let parameters = ["name": "John", "email": "john@example.com"]
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
3. Thực hiện dataTask và xử lý response
let dataTask = session.dataTask(with: request) { data, response, error in
// 1. Kiểm tra lỗi network
if let error = error {
print("Network error: \(error.localizedDescription)")
return
}
// 2. Kiểm tra HTTP response
guard let httpResponse = response as? HTTPURLResponse,
let receivedData = data else {
print("Invalid HTTP response")
return
}
// 3. Xử lý status code
switch httpResponse.statusCode {
case 200...299:
print("Success: \(httpResponse.statusCode)")
// Parse JSON response
if let json = try? JSONSerialization.jsonObject(with: receivedData) {
print("Response: \(json)")
}
case 400...499:
print("Client error: \(httpResponse.statusCode)")
case 500...599:
print("Server error: \(httpResponse.statusCode)")
default:
print("Unexpected status: \(httpResponse.statusCode)")
}
}
dataTask.resume() // Quan trọng: phải gọi resume() để bắt đầu task
Hàm hoàn chỉnh tái sử dụng
func postRequest(to urlString: String,
parameters: [String: Any],
completion: @escaping (Result<[String: Any], Error>) -> Void) {
guard let url = URL(string: urlString) else {
completion(.failure(NSError(domain: "Invalid URL", code: -1)))
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let httpResponse = response as? HTTPURLResponse,
let data = data else {
completion(.failure(NSError(domain: "Invalid response", code: -2)))
return
}
switch httpResponse.statusCode {
case 200...299:
if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
completion(.success(json ?? [:]))
} else {
completion(.failure(NSError(domain: "Parse error", code: -3)))
}
default:
let errorMsg = String(data: data, encoding: .utf8) ?? "Unknown error"
completion(.failure(NSError(domain: errorMsg, code: httpResponse.statusCode)))
}
}.resume()
}
// Sử dụng
postRequest(to: "https://api.example.com/users",
parameters: ["name": "John", "age": 30]) { result in
switch result {
case .success(let json):
print("Thành công: \(json)")
case .failure(let error):
print("Lỗi: \(error.localizedDescription)")
}
}
Lưu ý quan trọng
- App Transport Security (ATS): Mặc định yêu cầu HTTPS. Cần cấu hình Info.plist nếu gọi HTTP
- Timeout: Cấu hình
configuration.timeoutIntervalForRequest = 30 - Background session: Dùng
URLSessionConfiguration.backgroundcho upload/download lớn - Codable: Nên dùng
JSONEncoder/Decodervới struct conformCodablethay vì JSONSerialization - Authentication: Thêm header Authorization:
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
Info.plist cho HTTP (nếu cần)
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Lưu ý: Ví dụ này không có output thực tế vì cần API server thật để test.