В этом уроке, вы изучите как отправлять HTTP POST запрос в Swift и как читать HTTP ответ и тело ответа. Этот урок включает в себя:
- Отправка HTTP POST запрос
- Конверкация параметров Query строки в JSON
- Rонвертация структуры Swift в JSON
- Установка хедеров HTTP запроса
- Чтение HTTP ответа
- Чтение HTTP хедеров ответа
- Чтение HTTP тела ответа как строки
- Чтение HTTP тела ответа как JSON
Чтобы узнать как отправить HTTP GET запрос пожалуйста прочтите урок: HTTP GET Request Example in Swift или переведенную версию
Общедоступный веб сервис RESTful
В этом уроке, вы увидите общедоступный и бесплатный на момент написания этого урока веб сервис RESTful: https://jsonplaceholder.typicode.com. Это сервис позволяет мне отправлять HTTP запросы на него и получать обратно JSON ответ. На пример, если вы откроете URL в браузере: https://jsonplaceholder.typicode.com/todos/1 вы получите следующий JSON документ:
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
Я так же могу отправить HTTP POST запрос на https://jsonplaceholder.typicode.com/todos и получить обратно созданную запись. На пример, если послать HTTP POST запрос содержащий JSON с полезными данными в теле запроса:
{
"userId": 300,
"title": "delectus aut autem",
"completed": false
}
То мы получим обратно ответ похожий на этот:
{
"userId": "300",
"title": "My urgent task",
"completed": "false",
"id": 201
}
Итак давай те попробуем посмотреть как это работает в Swift.
Отправка HTTP POST запроса
Ниже очень простой пример того как вы можете отправить HTTP POST запрос в Swift. Пожалуйста обратите внимание на комментарии в коде.
// Prepare URL
let url = URL(string: "https://jsonplaceholder.typicode.com/todos")
guard let requestUrl = url else { fatalError() }
// Prepare URL Request Object
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
// HTTP Request Parameters which will be sent in HTTP Request Body
let postString = "userId=300&title=My urgent task&completed=false";
// Set HTTP Request Body
request.httpBody = postString.data(using: String.Encoding.utf8);
// Perform HTTP Request
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
// Check for Error
if let error = error {
print("Error took place \(error)")
return
}
// Convert HTTP Response Data to a String
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString)")
}
}
task.resume()
Пожалуйста обратите как в этом фрагменте кода мы конвертируем объект Даты в строку. Результат HTTP POST запроса приведен ниже, он должен вывести следующую JSON строку:
{
"userId": "300",
"title": "My urgent task",
"completed": "false",
"id": 201
}
Ниже здесь как выглядит код в моем Xcode плейграунде:
Установка хедеров HTTP запроса
Если ваш запрос HTTP должен содержать конкретные хедеры HTTP запроса, тогда ниже приведен привет как вы можете это сделать.
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
// Set HTTP Request Header
request.setValue("application/json", forHTTPHeaderField: "Accept")
Вы можете указать больше чем один хедер
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
Чтение хедеров HTTP ответа
Как только вы получили HTTP ответ, вы можете читать все хедеры из ответа HTTP из HTTPURLResponse объекта
Чтение всех хедеров
let allHeaderFields:[AnyHashable : Any] = response.allHeaderFields
print("All headers: \(allHeaderFields)")
Чтение конкретных значений хедера HTTP
let contentTypeHeader = response.value(forHTTPHeaderField: "Content-Type")
и здесь как вы можете использовать ответ HTTP когда он получен:
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let response = response as? HTTPURLResponse {
// Read all HTTP Response Headers
print("All headers: \(response.allHeaderFields)")
// Read a specific HTTP Response Header by name
print("Specific header: \(response.value(forHTTPHeaderField: "Content-Type") ?? " header not found")")
}
}
task.resume()
Чтение тела HTTP ответа
Когда HTTP ответ пришел, вам вероятно нужно прочитать тело HTTP ответа. Используйте фрагмент кода ниже для конвертации тела/даты HTTP ответа в человеко читаемые строковые значения.
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString)")
}
Вот как выглядит код если используем URLSession dataTesk
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let data = data, let dataString = String(data: data, encoding: .utf8) {
print("Response data string:\n \(dataString)")
}
}
task.resume()
Swift структура как тело ответа
Вы так же можете отправить Swift структуру в теле HTTP ответа. На пример, вместо отправки параметра HTTP запроса как мы делали в примере выше userId=300&title=My urgent task&completed=false, мы можем создать Swift структуру и отправить как тело HTTP ответа.
Следующие параметры строк запроса так же могут бы представлены следующим образом:
struct ToDoResponseModel: Codable {
var userId: Int
var id: Int?
var title: String
var completed: Bool
}
let newTodoItem = ToDoResponseModel(userId: 300, title: "Urgent task 2", completed: true)
Используя JSONEncoder() мы можем закодировать Swift структуру ниже в JSON дату и отправить как тело запроса.
let jsonData = try JSONEncoder().encode(newTodoItem)
request.httpBody = jsonData
Обратите внимание: Не забудьте установить хедеры HTTP: Accept и Content-Type to application/json.
// Set HTTP Request Headers
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
На пример:
struct ToDoResponseModel: Codable {
var userId: Int
var id: Int?
var title: String
var completed: Bool
}
let url = URL(string: "https://jsonplaceholder.typicode.com/todos")
guard let requestUrl = url else { fatalError() }
var request = URLRequest(url: requestUrl)
request.httpMethod = "POST"
// Set HTTP Request Header
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let newTodoItem = ToDoResponseModel(userId: 300, title: "Urgent task 2", completed: true)
let jsonData = try JSONEncoder().encode(newTodoItem)
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if let error = error {
print("Error took place \(error)")
return
}
guard let data = data else {return}
do{
let todoItemModel = try JSONDecoder().decode(ToDoResponseModel.self, from: data)
print("Response data:\n \(todoItemModel)")
print("todoItemModel Title: \(todoItemModel.title)")
print("todoItemModel id: \(todoItemModel.id ?? 0)")
}catch let jsonErr{
print(jsonErr)
}
}
task.resume()
Конвертация даты Ответа в Swift структуру
Когда HTTP ответ получен, мы можем его данные JSON декодировать в Swift структуру. В примере кода ниже мы уже это сделали. Для конвертации объекта даты из JSON мы будем использовать JSONDecoder(). На пример:
do{
let todoItemModel = try JSONDecoder().decode(ToDoResponseModel.self, from: data)
print("Response data:\n \(todoItemModel)")
print("todoItemModel Title: \(todoItemModel.title)")
print("todoItemModel id: \(todoItemModel.id ?? 0)")
}catch let jsonErr{
print(jsonErr)
}
Вот как выглядит мой код в Xcode плейграунде сейчас:
Я надеюсь этот урок был полезным для вас. Проверьте другие уроки Swift и вы найдете много полезного кода и примеры для использования.
Чтобы узнать как отправить HTTP GET запрос пожалуйста прочтите урок: HTTP GET Request Example in Swift или переведенную версию