JavaScript · API · Начальный

Заголовки и эхо-эндпоинт

5 задач

Добавляйте кастомные HTTP-заголовки к запросам и используйте эхо-эндпоинт для проверки.

HTTP-заголовки

#
HTTP-заголовки — это пары ключ-значение, передаваемые вместе с запросом или ответом: они несут метаданные о типе контента, токенах аутентификации и кастомной информации. В `fetch` заголовки запроса устанавливаются в объекте options: ```javascript const response = await fetch(url, { headers: { 'Authorization': 'Token abc123', 'X-Custom-Header': 'my-value', }, }); ``` Можно также использовать класс `Headers` для более структурированного подхода: ```javascript const headers = new Headers(); headers.set('Authorization', 'Token abc123'); headers.set('X-Request-ID', '42'); const response = await fetch(url, { headers }); ``` Эндпоинт `/api/echo/` отражает обратно именно то, что вы отправили — он полезен для проверки того, что заголовки приходят так, как ожидается: ```javascript const response = await fetch('https://apilearn.tukas.dev/api/echo/', { headers: { 'X-Custom-Header': 'hello' }, }); const data = await response.json(); // data.headers содержит заголовки, полученные сервером console.log(data.headers['X-Custom-Header']); // "hello" ``` Эхо-эндпоинт возвращает: ```javascript { method: "GET", headers: { /* все заголовки запроса */ }, body: null, query_params: {} } ```

Использование эхо-эндпоинта

#
Проверяем, какие заголовки мы фактически отправляем: ```javascript const BASE_URL = 'https://apilearn.tukas.dev'; async function inspectHeaders() { const response = await fetch(`${BASE_URL}/api/echo/`, { headers: { 'X-My-Header': 'test-value', 'X-Request-ID': '123', }, }); const data = await response.json(); console.log('Метод:', data.method); console.log('Мой заголовок:', data.headers['X-My-Header']); console.log('Все заголовки:', data.headers); } inspectHeaders(); ``` Вспомогательная функция, создающая обёртку `fetch` с дефолтными заголовками: ```javascript function createClient(baseUrl, token) { const defaultHeaders = { 'Authorization': `Token ${token}`, 'Content-Type': 'application/json', }; return async function apiFetch(path, options = {}) { const response = await fetch(`${baseUrl}${path}`, { ...options, headers: { ...defaultHeaders, ...options.headers }, }); return response.json(); }; } // Токен показан в следующей теме const client = createClient(BASE_URL, 'YOUR_TOKEN'); const profile = await client('/api/users/profile/'); console.log(profile.username); ``` Проверяем, что `Content-Type` установлен при отправке JSON: ```javascript const response = await fetch(`${BASE_URL}/api/echo/`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key: 'value' }), }); const echo = await response.json(); console.log(echo.headers['Content-Type']); // "application/json" ```

Справочник заголовков и эхо

#
**Установка заголовков в fetch** ```javascript // Объектный литерал (самый простой способ) fetch(url, { headers: { 'X-Key': 'value' } }) // Класс Headers const headers = new Headers({ 'X-Key': 'value' }); headers.set('X-Other', 'val2'); fetch(url, { headers }) ``` **Распространённые заголовки** ``` Authorization Токен: "Token <token>" JWT: "Bearer <access_token>" Content-Type Для POST/PATCH/PUT с JSON-телом: "application/json" X-* Любой кастомный заголовок, начинающийся с X- ``` **Эхо-эндпоинт** ``` GET /api/echo/ Возвращает детали запроса обратно как JSON ``` **Форма ответа эхо** ```javascript { method: "GET", path: "/api/echo/", query_params: {}, headers: { "X-My-Name": "Alice", // кастомные заголовки сохраняют оригинальный регистр ... }, body: null, content_type: null, auth: { authenticated: false, type: null, user: null, user_id: null } } ``` **Регистр кастомных заголовков** ``` Сервер возвращает кастомные заголовки в оригинальном регистре. "X-My-Name" остаётся "X-My-Name" в ответе эхо. ``` **Слияние дефолтных и per-request заголовков** ```javascript const merged = { ...defaultHeaders, ...requestHeaders }; ```
01

Отправить кастомный заголовок

#

Отправьте GET-запрос к `/api/echo/` с кастомным заголовком `X-My-Name: YourName`. Выведите значение этого заголовка из ответа эхо.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // GET /api/echo/ с заголовком X-My-Name
  // вывести отражённое значение заголовка
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/echo/`, {
    headers: { 'X-My-Name': 'Alice' },
  });
  const data = await response.json();
  console.log(data.headers['X-My-Name']);
}

main();
02

Отправить несколько заголовков

#

Отправьте GET `/api/echo/` с тремя заголовками: `X-App: my-app`, `X-Version: 1.0` и `X-Request-ID: 42`. Выведите полный объект `headers` из ответа.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // отправить 3 кастомных заголовка, вывести data.headers
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/echo/`, {
    headers: {
      'X-App': 'my-app',
      'X-Version': '1.0',
      'X-Request-ID': '42',
    },
  });
  const data = await response.json();
  console.log(data.headers);
}

main();
03

Проверить метод и параметры запроса через эхо

#

Отправьте GET `/api/echo/?color=blue&size=large`. Выведите метод и объект `query_params` из ответа.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // GET /api/echo/ с двумя параметрами запроса
  // вывести method и query_params
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const params = new URLSearchParams({ color: 'blue', size: 'large' });
  const response = await fetch(`${BASE_URL}/api/echo/?${params}`);
  const data = await response.json();
  console.log(data.method);
  console.log(data.query_params);
}

main();
04

POST с заголовком Content-Type

#

Отправьте POST к `/api/echo/` с JSON-телом `{name: "test"}` и заголовком `Content-Type: application/json`. Выведите отражённый заголовок `Content-Type` и поле `body`.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  // POST /api/echo/ с JSON-телом и заголовком Content-Type
  // вывести content-type заголовок и body из ответа
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const response = await fetch(`${BASE_URL}/api/echo/`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ name: 'test' }),
  });
  const data = await response.json();
  console.log(data.headers['content-type'] ?? data.headers['Content-Type']);
  console.log(data.body);
}

main();
05

Использовать класс Headers

#

Создайте объект `Headers` с помощью `.set()`, добавьте минимум два кастомных заголовка, затем передайте его в GET-запрос к `/api/echo/`. Выведите отражённые заголовки.

const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const headers = new Headers();
  // добавить заголовки через .set()
  // fetch и вывести отражённые заголовки
}

main();
Решение
const BASE_URL = 'https://apilearn.tukas.dev';

async function main() {
  const headers = new Headers();
  headers.set('X-Client', 'js-api-course');
  headers.set('X-Version', '2.0');

  const response = await fetch(`${BASE_URL}/api/echo/`, { headers });
  const data = await response.json();
  console.log(data.headers);
}

main();