Создание запроса HTTP POST
Прежде чем посылать произвольные данные, попробуем отправить на сервер
фрагмент текста. Вот как это можно сделать:
iOS
163
let data = "text to send".data(using: .utf8)
let url = URL(string: "https://www.oreilly.com")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.httpBody = data
let task =
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
...
}
task.resume()
Это простой пример, но обычно требуется отправлять на сервер структури
-
рованные текстовые строки, часто в формате JSON или в виде списка пар ключ/
значение. Для отправки таких строк удобно использовать объект
URLComponents
,
с помощью которого можно создавать списки пар ключ/значение, как показа
-
но ниже:
var components = URLComponents()
components.queryItems = [
URLQueryItem(name: "name", value: "O'Reilly"),
URLQueryItem(name: "isAwesome", value: "true")
]
let url = URL(string: "https://www.oreilly.com")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.httpBody = components.query?.data(using: .utf8)
let task =
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
...
}
task.resume()
Этот код сначала создает экземпляр
URLComponents
. Затем добавляет в его
свойство
queryItems
элементы – объекты
URLQueryItem
с парами ключ/значение.
После этого объект преобразуется в строку и добавляется в свойство
httpBody
объекта
URLRequest
.
Также часто бывает нужно отправить произвольные данные, не организо
-
ванные в пары ключ/значение. Вот пример выгрузки файла на сервер:
let data = "file data".data(using: .utf8)!
let url = URL(string: "http://www.example.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
let task = URLSession.shared.uploadTask(with: request, from: data)
task.resume()
Здесь сначала создается строка данных, представляющая наш фиктивный
файл, file data, содержимое которого преобразуется в объект
Data
, чтобы подго
-
товить его к последующей отправке. Затем определяется URL с адресом
http://
164
Сетевые взаимодействия
www.example.com
(это фиктивный адрес и в данном примере играет роль за
-
полнителя) и передается в новый объект
URLRequest
, который мы уже исполь
-
зовали в примере отправки запроса POST.
URLRequest
– это абстракция нашего
запроса. Этот объект позволяет произвести некоторые настройки перед от
-
правкой запроса на сервер. В данном примере мы настраиваем используемый
метод HTTP:
POST
. Значение свойства
httpMethod
отображается непосредственно
в стандартный глагол REST, по умолчанию используется
GET
.
Наконец, в этом примере, так же как в примерах в предыдущем разделе, соз
-
дается задание, однако в этом случае создается задание
URLSessionUploadTask
,
для чего вызывается метод
uploadTask
. Чтобы запустить задание отправки объ
-
екта
data
на сервер и выполнить запрос, вызывается метод
resume()
.
Это простой пример. Вероятно, сервер вернет какие-то данные с информа
-
цией об обработке запроса, включая информацию об успехе или неудаче. Что
-
бы получить эту информацию, можно использовать перегруженную версию
метода
uploadTask
, как показано ниже:
...
let task =
URLSession.shared.uploadTask(with: request, from: data) { (data, response, error) in
// Обработать в error ошибки, возникшие на стороне клиента
// Обработать в response ошибки, возникшие на стороне сервера
// Обработать успешное выполнение запроса,
// используя полученный объект data
}
Большинство современных API принимают структурированные данные, на
-
пример, в формате JSON и возвращают ответ в формате JSON. Наш упрощен
-
ный пример отправки строки с данными легко можно распространить на такие
случаи без внесения существенных изменений, кроме создания структуры для
данных. Ниже приводится законченный пример, демонстрирующий отправку
данных в формате JSON и обработку ответа:
// Определение объекта для представления данных
struct Book: Codable {
let title: String
let isbn: String
}
// Заполнить структуру данными
let book = Book(title: "Native Application Development", isbn: "this ISBN")
// Преобразовать структуру в объект Data для передачи в запрос
let data = try! JSONEncoder().encode(book)
// Создать запрос
let url = URL(string: "http://www.example.com")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Tye")
// Создать и запустить задание
iOS
165
let task =
URLSession.shared.uploadTask(with: request, from: data) { (data, response, error) in
// Обработать ошибки, возникшие на стороне клиента
if let error = error {
print(error.localizedDescription)
return
}
// Обработать ошибки, возникшие на стороне сервера
guard let response =
response as? HTTPURLResponse, response.statusCode < 300 else {
print("A server error occured.")
return
}
// Проверить наличие возвращаемых данных
guard let data = data else {
print("No data returned.")
return
}
// Декодировать полученный фрагмент JSON в экземпляр Book
do {
let book = try JSONDecoder().decode(Book.self, from: data)
print("The book's title is \(book.title) and the ISBN is \(book.isbn)")
} catch {
print("Could not decode response to JSON")
}
}
task.resume()
Пример выглядит довольно объемным, но если присмотреться внимательно,
вы найдете лишь несколько строк с существенными изменениями. Во-первых,
в начале примера определяется структура для представления данных. Затем
с помощью
JSONEncoder
эта структура преобразуется в объект
Data
.
JSONEncoder
входит в состав стандартной библиотеки Swift и предлагает простой метод для
сериализации и десериализации объектов JSON.
Существует целая глава, посвященная «транспортным данным», таким как
JSON. Вы можете проверить это для получения дополнительной информации
о функциональности и доступных методах.
Далее в книге вы найдете отдельную главу, посвященную «транспортировке дан
-
ных». В ней приводится более подробная информация об имеющихся методах
и возможностях.
Следующее существенное изменение можно заметить в строке
...
request.setValue("application/json", forHTTPHeaderField: "Content-Tye")
Эта команда добавляет в запрос HTTP-заголовок
ContentType
со значением
application/json
. Аналогично можно добавить другие HTTP-заголовки, но для
большинства API достаточно явно указать, что данные посылаются в формате
JSON.
166
Сетевые взаимодействия
Остальной код в вышеприведенном примере выглядит знакомым по преды
-
дущим примерам, за исключением обработчиков. Здесь выполняются некото
-
рые проверки на наличие ошибок на стороне клиента и/или сервера, а также
данных, возвращаемых сервером. Затем используется новый объект
JSONDe
coder
, чтобы преобразовать полученный объект
data
(который на самом деле
просто хранит данные в формате JSON) непосредственно в экземпляр
Book
, ко
-
торый, в свою очередь, используется для вывода свойств
title
и
isbn
.
Большинство сетевых операций, реализованных в
URLSession
, имеют опреде
-
ленные сходства. Однако, чтобы загрузить файл с сервера, придется написать
дополнительную логику, учитывающую несколько иной набор требований. Да
-
вайте посмотрим, что это за логика, рассмотрев в следующем разделе загрузку
двоичных файлов.
Do'stlaringiz bilan baham: |