Для взаимодействия с http-сервером в клиентском приложении применяется класс HttpClient из библиотеки dart:io
Для создания объекта HttpClient применяется фабричный конструктор:
HttpClient({SecurityContext? context})
В качестве необязательного параметра он получает объект SecurityContext, который устанавливает дополнительные настройки для взаимодействия по защищенному протоколу https (например, сертификаты и ключи).
Для завершения работы HttpClient вызывается метод close():
void close({bool force = false})
Если параметр force
равен false
(значение по умолчанию), HttpClient продолжит работать, пока не будут
закрыты все активные подключения. Если же force
равно true
, то при вызове метода автоматически закрываются все активные подключения и освобождаются
все ресурсы.
import 'dart:io'; void main() async { var client = HttpClient(); // создаем клиент client.close(); // завершаем его работу }
HttpClient содержит ряд методов, которые отправляют на http-сервер запрос в виде объекта HttpClientRequest и получают ответ в виде объекта HttpClientResponse:
delete(String host, int port, String path)
: отправляет запрос типа DELETE, используя хост host, порту port и путь path
deleteUrl(Uri url)
: отправляет запрос типа DELETE по адресу url
get(String host, int port, String path)
: отправляет запрос типа GET
getUrl(Uri url)
: отправляет запрос типа GET
head(String host, int port, String path)
: отправляет запрос типа HEAD
headUrl(Uri url)
: отправляет запрос типа HEAD
patch(String host, int port, String path)
: отправляет запрос типа PATCH
patchUrl(Uri url)
: отправляет запрос типа PATCH
post(String host, int port, String path)
: отправляет запрос типа POST
postUrl(Uri url)
: отправляет запрос типа POST
put(String host, int port, String path)
: отправляет запрос типа PUT
putUrl(Uri url)
: отправляет запрос типа PUT
Все эти методы однотипны. Одна их часть принимает хост и порт приложения и путь запроса. Другая часть методов принимает адрес Uri. Но в качестве результата все эти методы возвращают Future<HttpClientRequest>. Рассмотрим на примере отправки GET-запроса к сайту "www.google.com":
import 'dart:io'; import 'dart:convert'; void main() async { var client = HttpClient(); try { // создаем запрос HttpClientRequest request = await client.get("www.google.com", 80, "/"); // получаем ответ HttpClientResponse response = await request.close(); // обрабатываем ответ final stringData = await response.transform(utf8.decoder).join(); print(stringData); } finally { client.close(); } }
Здесь создаем запрос идет к главной странице (путь "/") на хосте "www.google.com" с использованием порта 80.
HttpClientRequest request = await client.get("www.google.com", 80, "/");
Результатом метода является объект класса HttpClientRequest. При создании этого объекта устанавливает подключения, однако сами данные еще не отправляются. Для отправки запроса у HttpClientRequest вызывается метод close()
HttpClientResponse response = await request.close();
Результатом отправки запроса является ответ - объект HttpClientResponse, который представляет поток для чтения. Этот поток содержит ответ в виде набора байт - объекта List<int>
. Однако поскольку мы ожидаем получить от google.com веб-страницу, то мы можем преобразовать ответ в строку
final stringData = await response.transform(utf8.decoder).join();
Здесь метод response.transform(utf8.decoder)
преобразует байты в строку с помощью декодера utf8.decoder
. А метод join()
соединяет все отдельные преобразованные данные в одну строку.
В итоге мы получим в текстовом виде веб-страницу www.google.com:
Подобным образом мы могли бы использовать и другую версию метода, которая принимает объект Uri. Конструктор этого объекта позволяет более точно настроить адрес запроса:
Uri( {String? scheme, // схема - http или https String? userInfo, // логин и пароль пользователя String? host, // хост int? port, // порт String? path, // путь Iterable<String>? pathSegments, // сегменты пути, разделенные слешем String? query, // строка запроса Map<String, dynamic>? queryParameters, // параметры строки запроса String? fragment} // фрагмент (часть после #) )
Пример запроса с использованием Uri
:
import 'dart:io'; import 'dart:convert'; void main() async { var client = HttpClient(); try { // создаем запрос HttpClientRequest request = await client.getUrl(Uri(scheme:"https", host:"www.google.com", path:"/", query:"q=metanit.com")); // получаем ответ HttpClientResponse response = await request.close(); // обрабатываем ответ final stringData = await response.transform(utf8.decoder).join(); print(stringData); } finally { client.close(); } }
Здесь с помощью параметров, переданных в конструктор Uri, фактически будет формироваться адрес https://www.google.com/?q=metanit.com
. В качестве результата запроса опять же получаем веб-страницу в текстовом виде, которую затем можно обработать.
Аналогичным образом мы можем отправлять запросы к любому серверу. Например, определим собственный http-сервер на Dart. Для этого создадим файл server.dart со следующим кодом:
import 'dart:io'; void main() async { var server = await HttpServer.bind(InternetAddress.anyIPv6, 8888); print("Сервер запущен..."); await server.forEach((HttpRequest request) { var response = request.response; response.write(DateTime.now()); response.close(); }); }
Здесь сервер в ответ на любой запрос отправляет текущие дату и время.
И определим файл http-клиента main.dart со следующим кодом:
import 'dart:io'; import 'dart:convert'; void main() async { var client = HttpClient(); try { // создаем запрос HttpClientRequest request = await client.get("localhost", 8888, "/"); // получаем ответ HttpClientResponse response = await request.close(); // обрабатываем ответ final stringData = await response.transform(utf8.decoder).join(); print(stringData); } finally { client.close(); } }
Поскольку наш сервер запускается локально на том же компьютере, что клиент, и использует порт 8888, то для подключения к серверу в качестве хоста используем "localhost", а в качестве порта - 8888. В данном случае также получаем ответ и конвертируем его в строку.
Запустим сначала сервер server.dart, а затем клиент main.dart
После запуска клиента произойдет обращение к серверу, и сервер отправит в ответ клиенту дату и время, которые клиент выведет на консоль.