Отправка запросов на сервер. HttpClient

Последнее обновление: 13.04.2023

Для взаимодействия с 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:

Отправка запроса к ресурсу с помощью класса HttpClient в языке Dart

Подобным образом мы могли бы использовать и другую версию метода, которая принимает объект 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-сервером

Аналогичным образом мы можем отправлять запросы к любому серверу. Например, определим собственный 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

Взаимодействие http-сервера и http-клиента в языке программирования Dart

После запуска клиента произойдет обращение к серверу, и сервер отправит в ответ клиенту дату и время, которые клиент выведет на консоль.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850