JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Отправка HTTP-запросов с телом и заголовками в Angular

Отправка HTTP-запросов с телом и заголовками в Angular

Модуль 4: Node.js, Next.js и Angular
17 уровень , 5 лекция
Открыта

1. HTTP-запросы с телом: POST и PUT

HTTP-запрос — это не просто "дай мне что-нибудь". Это полноценное письмо серверу, где можно указать метод (GET, POST, PUT, DELETE), добавить тело (body) с данными (например, ваш новый пост или форму регистрации), а ещё — приложить кучу конвертов с дополнительной информацией (заголовки: Content-Type, Authorization и др.).

Примеры из жизни:

  • Отправка формы регистрации пользователя (POST с JSON в теле).
  • Обновление данных профиля (PUT с телом).
  • Аутентификация (заголовок Authorization).
  • Загрузка файла (POST с multipart/form-data).
  • Фильтрация/поиск (GET с query-параметрами или POST с фильтром в теле).

В Angular всё это делается через сервис HttpClient. Давайте разберёмся, как!

POST: отправка данных на сервер

Когда вы хотите что-то создать (например, нового пользователя), используйте метод post. Он принимает минимум два аргумента: URL и тело запроса.

import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient) {}

addUser(user: { name: string; email: string }) {
  return this.http.post('/api/users', user);
}

В этом примере мы отправляем объект user на сервер. Angular автоматически преобразует объект в JSON и устанавливает заголовок Content-Type: application/json.

Пример с подпиской:

this.addUser({ name: 'Вася', email: 'vasya@example.com' })
  .subscribe({
    next: response => console.log('Пользователь создан!', response),
    error: err => console.error('Ошибка:', err)
  });

PUT: обновление данных

PUT похож на POST, но обычно используется для обновления существующего ресурса.

updateUser(id: number, user: { name: string; email: string }) {
  return this.http.put(`/api/users/${id}`, user);
}

DELETE: иногда тоже с телом (редко)

Стандарт HTTP не запрещает отправлять тело в DELETE-запросе, но большинство серверов этого не ждёт. Обычно DELETE — без тела, но если вдруг нужно, Angular позволяет передать его третьим параметром (options).

2. Передача заголовков (headers)

Иногда сервер требует дополнительные заголовки: например, токен авторизации, тип содержимого, настройки кеширования и т.д.

В Angular для этого используется класс HttpHeaders. Заголовки передаются через третий параметр метода запроса:

import { HttpHeaders } from '@angular/common/http';

const headers = new HttpHeaders({
  'Authorization': 'Bearer my-super-secret-token',
  'X-Custom-Header': 'SomeValue'
});

this.http.post('/api/secure', { data: 123 }, { headers })
  .subscribe(...);

Особенности работы с HttpHeaders

  • HttpHeadersиммутабельный (неизменяемый) объект. Методы set, append возвращают новый объект, а не меняют существующий.
  • Можно создавать "цепочки":
const headers = new HttpHeaders()
  .set('Authorization', 'Bearer supertoken')
  .set('X-Request-ID', 'abc123');
  • Если вы хотите добавить заголовок к уже существующим:
let headers = new HttpHeaders();
headers = headers.set('Authorization', 'Bearer token');
headers = headers.set('Another', 'value');

3. Полезные нюансы

Передача query-параметров

Иногда сервер ждёт параметры не в теле, а в строке запроса (например, фильтр, пагинация):

import { HttpParams } from '@angular/common/http';

const params = new HttpParams()
  .set('page', '2')
  .set('pageSize', '10');

this.http.get('/api/users', { params })
  .subscribe(...);

Полная сигнатура HTTP-запроса

Для всех методов (get, post, put, delete, ...) третий параметр — это объект с дополнительными настройками:

this.http.post(
  '/api/users',
  { name: 'Петя' },
  {
    headers: new HttpHeaders({ 'Authorization': 'Bearer token' }),
    params: new HttpParams().set('role', 'admin'),
    observe: 'body', // или 'response', если нужны заголовки ответа
    responseType: 'json' // или 'text', 'blob'
  }
)
.subscribe(...);

Отправка произвольных типов данных

JSON (по умолчанию)
Angular автоматически сериализует объект в JSON, если вы отправляете обычный объект.

FormData (отправка файлов)
Если нужно отправить файл, используйте FormData:

const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('description', 'Мой файл');

this.http.post('/api/upload', formData)
  .subscribe(...);

Внимание: Angular сам выставит нужный заголовок Content-Type: multipart/form-data — не нужно делать это вручную!

Текст или Blob
Если сервер ждёт обычный текст или бинарные данные:

this.http.post('/api/text', 'Привет, сервер!', {
  headers: new HttpHeaders({ 'Content-Type': 'text/plain' }),
  responseType: 'text'
})
.subscribe(...);

4. Пример: Асинхронная отправка формы регистрации с заголовками

Давайте добавим в наше учебное приложение функцию регистрации пользователя, с отправкой тела и заголовка авторизации.

user.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Injectable({ providedIn: 'root' })
export class UserService {
  constructor(private http: HttpClient) {}

  register(user: { name: string; email: string; password: string }) {
    const headers = new HttpHeaders({
      'Authorization': 'Bearer test-token'
    });

    return this.http.post('/api/register', user, { headers });
  }
}

user.component.ts

import { Component } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-user-register',
  template: `
    <form (ngSubmit)="onSubmit()">
      <input [(ngModel)]="user.name" name="name" placeholder="Имя">
      <input [(ngModel)]="user.email" name="email" placeholder="Email">
      <input [(ngModel)]="user.password" name="password" type="password" placeholder="Пароль">
      <button type="submit">Зарегистрироваться</button>
    </form>
  `
})
export class UserRegisterComponent {
  user = { name: '', email: '', password: '' };

  constructor(private userService: UserService) {}

  onSubmit() {
    this.userService.register(this.user)
      .subscribe({
        next: res => alert('Регистрация успешна!'),
        error: err => alert('Ошибка регистрации: ' + err.message)
      });
  }
}

5. Типичные ошибки при отправке HTTP-запросов с телом и заголовками

Ошибка №1: Попытка вручную выставить Content-Type для FormData
Если вы отправляете FormData (например, с файлом), не выставляйте Content-Type вручную! Браузер сам подставит нужный boundary, иначе сервер не сможет разобрать файл.

Ошибка №2: Мутирование HttpHeaders
Не забывайте, что HttpHeaders — иммутабельный. Каждый вызов set возвращает новый объект. Если вы делаете так:

const headers = new HttpHeaders();
headers.set('Authorization', 'Bearer token'); // ничего не произойдёт!

Заголовок не добавится! Нужно писать:

const headers = new HttpHeaders().set('Authorization', 'Bearer token');

Ошибка №3: Передача сложных объектов как query-параметров
Если вы пытаетесь передать массив или объект через HttpParams, Angular не сериализует их как JSON. Нужно сериализовать вручную или использовать несколько .set() для каждого значения.

Ошибка №4: Необработанные ошибки сервера
Если сервер возвращает ошибку (например, 400 или 500), а вы не подписались на error в subscribe/catchError, пользователь не узнает о проблеме.

Ошибка №5: Несовпадение Content-Type и типа тела
Если вы указали Content-Type: application/json, а отправляете строку или FormData — сервер может не понять ваш запрос. Следите за соответствием типа тела и заголовка.

Ошибка №6: Передача токена в теле вместо заголовка
Токены авторизации (например, JWT) всегда передаются в заголовке Authorization, а не в теле запроса. Не путайте!

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ