HTTP-запросы¶
30.09.2026
У HttpClient есть методы под разные HTTP-глаголы: ими и загружают данные, и меняют состояние на сервере. Каждый метод возвращает RxJS Observable. Подписка отправляет запрос, а когда сервер отвечает, Observable отдаёт результат.
На Observable, который создал HttpClient, можно подписаться сколько угодно раз. Каждая подписка делает новый запрос к серверу.
Объект параметров, который передают методу запроса, меняет свойства запроса и тип возвращаемого ответа.
Загрузка JSON¶
Данные с сервера чаще всего забирают GET-запросом через HttpClient.get(). У метода два аргумента: строка URL, откуда читать, и необязательный объект параметров запроса.
Например, конфигурация с условного API через HttpClient.get():
1 2 3 | |
Обобщённый аргумент типа говорит, что сервер вернёт данные типа Config. Аргумент необязателен: без него тип данных — Object.
Если структура данных неясна и в ней бывают undefined или null, в качестве типа ответа берите unknown, а не Object.
Обобщённый тип методов запроса — это утверждение о данных, которые вернул сервер. HttpClient не проверяет, что фактические данные совпадают с этим типом.
Другие типы данных¶
По умолчанию HttpClient считает, что сервер вернёт JSON. Для API не на JSON при запросе указывают ожидаемый тип ответа параметром responseType.
Значение responseType | Тип ответа |
|---|---|
'json' (по умолчанию) | JSON-данные указанного обобщённого типа |
'text' | строка |
'arraybuffer' | ArrayBuffer с сырыми байтами ответа |
'blob' | экземпляр Blob |
Например, сырые байты изображения .jpeg можно скачать в ArrayBuffer:
1 2 3 | |
Литерал для responseType
Значение responseType влияет на тип, который возвращает HttpClient, поэтому это должен быть литеральный тип, а не string.
Так получается само, если объект параметров — литерал. Если параметры вынесены в переменную или вспомогательный метод, литерал задают явно, например responseType: 'text' as const.
Изменение состояния на сервере¶
API, которые меняют состояние, часто ждут POST с телом: новое состояние или описание изменения.
Метод HttpClient.post() устроен как get(), но перед параметрами принимает дополнительный аргумент body:
1 2 3 | |
В body можно передать значения разных типов, и HttpClient сериализует их соответственно:
Тип body | Сериализация |
|---|---|
| string | обычный текст |
| number, boolean, array или обычный объект | JSON |
ArrayBuffer | сырые данные из буфера |
Blob | сырые данные с типом содержимого Blob |
FormData | данные в кодировке multipart/form-data |
HttpParams или URLSearchParams | строка в формате application/x-www-form-urlencoded |
Чтобы мутирующий запрос реально ушёл, на его Observable нужно вызвать .subscribe().
Параметры URL¶
Параметры, которые должны попасть в URL запроса, задают опцией params.
Проще всего передать объект-литерал:
1 2 3 4 5 6 7 | |
Если над сборкой или сериализацией параметров нужен больший контроль, передают экземпляр HttpParams.
Экземпляры HttpParams неизменяемы, их нельзя поменять на месте. Методы вроде append() возвращают новый экземпляр HttpParams с применённым изменением.
1 2 3 4 5 6 7 8 9 | |
HttpParams можно создать со своим HttpParameterCodec: он определяет, как HttpClient закодирует параметры в URL.
Своё кодирование параметров¶
По умолчанию HttpParams кодирует и декодирует ключи и значения встроенным HttpUrlEncodingCodec.
Свою реализацию HttpParameterCodec передают, чтобы задать кодирование и декодирование самостоятельно.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | |
Заголовки запроса¶
Заголовки запроса задают опцией headers.
Проще всего передать объект-литерал:
1 2 3 4 5 6 7 8 9 | |
Если над сборкой заголовков нужен больший контроль, передают экземпляр HttpHeaders.
Экземпляры HttpHeaders неизменяемы, их нельзя поменять на месте. Методы вроде append() возвращают новый экземпляр HttpHeaders с применённым изменением.
1 2 3 4 5 6 7 8 9 | |
События ответа сервера¶
Для удобства HttpClient по умолчанию возвращает Observable данных, которые отдал сервер (тело ответа). Иногда нужно посмотреть сам ответ, например прочитать конкретные заголовки.
Чтобы получить ответ целиком, ставят observe: 'response':
1 2 3 4 | |
Литерал для observe
Значение observe влияет на тип, который возвращает HttpClient, поэтому это должен быть литеральный тип, а не string.
Так получается само, если объект параметров — литерал. Если параметры вынесены в переменную или вспомогательный метод, литерал задают явно, например observe: 'response' as const.
Сырые события прогресса¶
Помимо тела или объекта ответа HttpClient может отдать поток сырых событий — моментов жизненного цикла запроса. События отмечают отправку запроса, приход заголовка ответа и завершение тела. Среди них бывают события прогресса: статус выгрузки и загрузки больших тел запроса или ответа.
События прогресса по умолчанию выключены (у них есть цена по производительности). Их включают параметрами reportUploadProgress и reportDownloadProgress.
Серверная часть fetch у HttpClient по умолчанию не поддерживает события прогресса выгрузки и бросает ошибку, если задать reportUploadProgress. Если приложению нужны события прогресса выгрузки, настройте HttpClient через withXhr() в provideHttpClient(...).
Чтобы наблюдать поток событий, ставят observe: 'events':
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Литерал для observe
Значение observe влияет на тип, который возвращает HttpClient, поэтому это должен быть литеральный тип, а не string.
Так получается само, если объект параметров — литерал. Если параметры вынесены в переменную или вспомогательный метод, литерал задают явно, например observe: 'events' as const.
У каждого HttpEvent в потоке есть type, который отличает смысл события:
Значение type | Смысл события |
|---|---|
HttpEventType.Sent | Запрос отправлен на сервер |
HttpEventType.UploadProgress | HttpUploadProgressEvent — прогресс выгрузки тела запроса |
HttpEventType.ResponseHeader | Получено начало ответа, включая статус и заголовки |
HttpEventType.DownloadProgress | HttpDownloadProgressEvent — прогресс загрузки тела ответа |
HttpEventType.Response | Ответ получен целиком, включая тело |
HttpEventType.User | Своё событие от HTTP-перехватчика. |
Ошибка запроса¶
HTTP-запрос может сорваться тремя способами:
- Сеть или соединение не дали запросу дойти до сервера.
- Запрос не успел ответить, когда был задан таймаут.
- Сервер получил запрос, но не смог его обработать и вернул ответ с ошибкой.
HttpClient собирает все такие ошибки в HttpErrorResponse и отдаёт их через канал ошибок Observable. У сетевых ошибок и таймаута код status равен 0, а error — экземпляр ProgressEvent. У ошибок сервера status — код, который вернул сервер, а error — тело ошибочного ответа. По ответу определяют причину и то, как её обработать.
В библиотеке RxJS есть операторы, которые удобны для обработки ошибок.
Оператор catchError превращает ошибочный ответ в значение для интерфейса. По нему интерфейс показывает страницу или значение ошибки и при необходимости сохраняет причину.
Иногда кратковременный сбой, например обрыв сети, роняет запрос неожиданно, и простой повтор его спасает. В RxJS есть операторы retry: они автоматически переподписываются на упавший Observable при определённых условиях. Например, retry() повторяет подписку заданное число раз.
Таймауты¶
Таймаут запроса задают параметром timeout — число миллисекунд рядом с остальными параметрами. Если запрос к серверу не завершился за это время, он прерывается, и приходит ошибка.
Таймаут относится только к самому HTTP-запросу к серверу. Это не таймаут всей цепочки обработки. Задержка, которую внесли перехватчики, на этот параметр не влияет.
1 2 3 4 5 6 7 8 9 10 11 12 | |
Расширенные параметры fetch¶
HttpClient в Angular поддерживает расширенные параметры Fetch API: они улучшают производительность и опыт пользователя. Параметры доступны на серверной части fetch, а она используется по умолчанию.
Параметры fetch¶
Следующие параметры тонко управляют поведением запроса на серверной части fetch.
Соединения keep-alive¶
Параметр keepalive позволяет запросу пережить страницу, которая его начала. Это особенно полезно для аналитики и журнала: запрос должен завершиться, даже если пользователь ушёл со страницы.
1 2 3 4 5 | |
Управление HTTP-кэшем¶
Параметр cache задаёт, как запрос взаимодействует с HTTP-кэшем браузера. Для повторяющихся запросов это заметно ускоряет работу.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Приоритет запроса и Core Web Vitals¶
Параметр priority указывает относительную важность запроса. Браузер лучше планирует загрузку ресурсов, и оценки Core Web Vitals растут.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Допустимые значения priority:
'high'— высокий приоритет, загрузка раньше (например, критичные данные пользователя и содержимое первого экрана)'low'— низкий приоритет, загрузка когда ресурсы свободны (например, аналитика и предзагрузка)'auto'— приоритет выбирает браузер по контексту запроса (по умолчанию)
Ставьте priority: 'high' запросам, которые влияют на отрисовку самого крупного содержимого (LCP), и priority: 'low' тем, что не затрагивают первый опыт пользователя.
Режим запроса¶
Параметр mode задаёт, как запрос ведёт себя с чужим источником, и определяет тип ответа.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Допустимые значения mode:
'same-origin'— только запросы того же источника, кросс-доменные падают'cors'— кросс-доменные запросы с CORS (по умолчанию)'no-cors'— простые кросс-доменные запросы без CORS, ответ непрозрачный
В браузере для чувствительных запросов, которые не должны уходить на другой источник, ставьте mode: 'same-origin'.
При SSR на Node.js HttpClient использует реализацию Fetch на Undici. Undici не применяет браузерные проверки CORS, поэтому mode: 'same-origin' не ограничивает серверные запросы. URL, на которые влияет пользователь, сверяйте с белым списком.
Обработка перенаправлений¶
Параметр redirect задаёт, что делать с ответами-перенаправлениями сервера.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Допустимые значения redirect:
'follow'— следовать перенаправлениям автоматически (по умолчанию)'error'— считать перенаправления ошибками'manual'— не следовать автоматически, вернуть ответ-перенаправление
Ставьте redirect: 'manual', когда перенаправления нужно обрабатывать своей логикой.
Учётные данные¶
Параметр credentials решает, уходят ли куки, заголовки авторизации и другие учётные данные с кросс-доменным запросом. Это особенно важно для аутентификации.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
Параметр withCredentials важнее credentials. Если заданы оба, withCredentials: true всегда даёт credentials: 'include', каким бы ни было явное значение credentials.
Допустимые значения credentials:
'omit'— никогда не отправлять учётные данные'same-origin'— отправлять учётные данные только для запросов того же источника (по умолчанию)'include'— всегда отправлять учётные данные, в том числе на другой источник
Ставьте credentials: 'include', когда куки или заголовки аутентификации нужно отправить на другой домен с поддержкой CORS. Не смешивайте credentials и withCredentials, чтобы не запутаться.
При SSR на Node.js credentials: 'include' сам не пересылает куки входящего запроса браузера. Параметр credentials не убирает заголовки Cookie и Authorization, которые добавлены явно. Undici пропускает часть заголовков, которые браузер запрещает, поэтому заголовки с учётными данными пересылайте только на доверенные источники.
Referrer¶
Параметр referrer задаёт, какие сведения об источнике перехода уходят с запросом. Это важно для приватности и безопасности.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Параметр referrer принимает:
- Строку с корректным URL — конкретный URL источника перехода
- Пустую строку
''— сведения об источнике перехода не отправляются 'about:client'— источник перехода по умолчанию (URL текущей страницы)
Для чувствительных запросов, где URL страницы-источника не должен утечь, ставьте referrer: ''.
Политика referrer¶
Параметр referrerPolicy задаёт, какая часть сведений об источнике перехода — URL страницы, которая делает запрос, — уходит вместе с HTTP-запросом. От этого зависят и приватность, и аналитика: видно, сколько данных открыто и насколько это безопасно.
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Параметр referrerPolicy принимает:
'no-referrer'— никогда не отправлять заголовокReferer.'no-referrer-when-downgrade'— отправлять источник перехода для того же источника и для безопасных запросов (HTTPS→HTTPS) и опускать его при переходе с безопасного источника на менее безопасный (HTTPS→HTTP).'origin'— отправлять только источник (схема, хост, порт), без пути и строки запроса.'origin-when-cross-origin'— полный URL для запросов того же источника и только источник для кросс-доменных.'same-origin'— полный URL для запросов того же источника и ничего для кросс-доменных.'strict-origin'— только источник, и только если уровень безопасности протокола не понижается (например, HTTPS→HTTPS). При понижении источник перехода опускается.'strict-origin-when-cross-origin'— поведение браузера по умолчанию. Полный URL для того же источника, источник для кросс-доменных запросов без понижения протокола, и ничего при понижении.'unsafe-url'— всегда полный URL, включая путь и строку запроса. Так можно раскрыть чувствительные данные, пользуйтесь осторожно.
Для запросов, где важна приватность, берите сдержанные значения: 'no-referrer', 'origin' или 'strict-origin-when-cross-origin'.
Целостность¶
Параметр integrity проверяет, что ответ не подменили: передаётся криптографический хеш ожидаемого содержимого. Это особенно полезно, когда скрипты и другие ресурсы грузятся с CDN.
1 2 3 4 5 6 7 8 9 | |
integrity требует точного совпадения содержимого ответа и переданного хеша. Если содержимое не совпало, запрос упадёт с сетевой ошибкой.
При SSR реализация Fetch читает всё тело ответа, чтобы проверить integrity, и только потом возвращает ответ — так требует стандарт Fetch. Angular применяет maxResponseBodySize только после того, как Fetch вернул ответ, поэтому этот предел не ограничивает данные, накопленные во время проверки целостности.
Целостность подресурса стоит включать, когда критичные ресурсы грузятся из внешних источников: так видно, что их не изменили. Хеши считают инструментами вроде openssl.
HTTP-Observable¶
Каждый метод запроса HttpClient создаёт и возвращает Observable запрошенного типа ответа. Чтобы пользоваться HttpClient, важно понимать, как устроены эти Observable.
HttpClient создаёт то, что в RxJS называют «холодными» Observable: реального запроса нет, пока на Observable не подпишутся. Только тогда запрос уходит на сервер. Несколько подписок на один и тот же Observable дают несколько запросов к серверу. Подписки независимы.
Observable от HttpClient можно считать заготовками реальных запросов к серверу.
После подписки отписка прерывает запрос, который ещё идёт. Это удобно, если подписка идёт через пайп async: запрос отменится сам, когда пользователь уйдёт со страницы. То же самое с комбинаторами RxJS вроде switchMap: отмена убирает устаревшие запросы.
Когда ответ приходит, Observable от HttpClient обычно завершаются (на это могут влиять перехватчики).
Из-за автоматического завершения утечка памяти маловероятна, даже если подписки HttpClient не снимать. Но, как и с любой асинхронной операцией, подписки лучше снимать, когда компонент уничтожается: иначе колбэк подписки может выполниться и упасть, пытаясь работать с уже уничтоженным компонентом.
Подписка через пайп async или операцию toSignal снимается корректно.
Практические приёмы¶
HttpClient можно внедрить и вызывать прямо из компонента, но обычно доступ к данным выносят в переиспользуемые внедряемые сервисы. Например, UserService прячет запрос данных пользователя по идентификатору:
1 2 3 4 5 6 7 8 | |
В компоненте @if вместе с пайпом async рисует интерфейс только после загрузки данных:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
Источник: https://angular.dev/guide/http/making-requests