Друкарня від WE.UA

RFC 7807. Що це і для чого він потрібен бекенд розробникам

Зміст

RFC 7807

Що таке RFC 7807?

RFC 7807 — це стандарт, що описує формат передачі помилок у HTTP API. Він пропонує використовувати уніфікований формат JSON-об'єкта, який називається "Problem Details". Ідея в тому, щоб зробити повідомлення про помилки структурованими, інформативними та зрозумілими як для розробників, так і для клієнтів.

Чому це важливо

Як часто вам доводилося бачити неструктуровані відповіді на помилки типу:

{
  "error": "INVALID_REQUEST",
  "message": "User ID is missing"
}

Начебто зрозуміло, але що робити з таким респонсом далі?
RFC 7807 дозволяє не лише стандартизувати ці повідомлення, а й надати більше контексту про те, що пішло не так і як це виправити. Завдяки цьому, помилки стають значно простішими для обробки.


Формат Problem Details

Основна структура відповіді:

{
  "type": "https://api.example.com/problems/invalid-user",
  "title": "Invalid User ID",
  "status": 400,
  "detail": "The user ID provided is not valid.",
  "instance": "/users/123"
}
  • type — URL, який описує тип проблеми (може бути реальним посиланням на документацію або просто строкою).

  • title — короткий опис проблеми.

  • status — HTTP статус-код.

  • detail — деталі помилки.

  • instance — URI запиту, що викликав проблему (необов'язково).

Можна також додавати кастомні поля для специфічних кейсів:

{
  "type": "https://api.example.com/problems/invalid-input",
  "title": "Invalid Input",
  "status": 422,
  "detail": "The input data is invalid.",
  "invalidField": "email"
}

Як виглядає респонс без RFC 7807 і з ним

Без RFC 7807:

{
  "error": "USER_NOT_FOUND",
  "message": "User with ID 123 not found"
}

З RFC 7807:

{
  "type": "https://api.example.com/problems/user-not-found",
  "title": "User Not Found",
  "status": 404,
  "detail": "User with ID 123 was not found in the database.",
  "instance": "/users/123"
}

Погодьтесь, другий варіант виглядає більш зрозуміло і гнучко для подальшої автоматизації.


Best Practices

  1. Використовуйте URL у полі type.
    Це може бути статична сторінка документації вашого API або умовний посилання на тип помилки. Наприклад: https://api.example.com/problems/invalid-input.

  2. Не додавайте зайвого.
    Поля, що не мають практичної користі, лише ускладнюють відповідь.

  3. Кастомізуйте для своєї доменної області.
    Ви можете додавати власні поля, але не змінюйте обов'язкові, описані у RFC.

  4. Обов'язково логуйте.
    Навіть якщо користувач отримує зрозумілий респонс, логування помилки на стороні сервера є критично важливим для дебагу.


Реалізація в Java Spring Boot

Налаштування Controller Advice

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(AuthenticationException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ProblemDetail handleAuthenticationError(AuthenticationException ex, HttpServletRequest request) {
        ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(
            HttpStatus.UNAUTHORIZED,
            ex.getMessage()
        );
        problemDetail.setType(URI.create("https://api.example.com/problems/authentication-failed"));
        problemDetail.setTitle("Authentication Failed");
        problemDetail.setInstance(URI.create(request.getRequestURI()));
        return problemDetail;
    }
}

Кастомна помилка

public class AuthenticationException extends RuntimeException {
    public AuthenticationException(String message) {
        super(message);
    }
}

Ендпоінт для автентифікації, наприклад, з використанням FIDO2

@RestController
@RequestMapping("/auth")
public class AuthenticationController {

    @PostMapping("/fido2")
    public ResponseEntity<String> authenticateWithFido2(@RequestBody Fido2Request request) {
        if (!fido2Service.validate(request)) {
            throw new AuthenticationException("Invalid FIDO2 credentials provided");
        }
        return ResponseEntity.ok("Authentication successful");
    }
}

Приклад респонсу при помилці автентифікації

{
  "type": "https://api.example.com/problems/authentication-failed",
  "title": "Authentication Failed",
  "status": 401,
  "detail": "Invalid FIDO2 credentials provided.",
  "instance": "/auth/fido2"
}

Інтеграція та взаємодія з іншими компонентами

Стандартизована взаємодія

  • Інші сервіси або фронтенд можуть очікувати однакову структуру помилок, що спрощує їх обробку.

  • Наприклад, фронтенд може мати єдиний обробник для всіх помилок із зрозумілими полями type, title, detail та status.

На фронтенді це може виглядати так:

fetch("/api/auth/fido2", { method: "POST", body: JSON.stringify(data) })
  .then(response => {
    if (!response.ok) {
      return response.json().then(error => {
        console.error(`Error Type: ${error.type}`);
        alert(error.title + ": " + error.detail);
      });
    }
  });

Машинна обробка помилок

  • Поле type дозволяє програмно класифікувати помилки. Наприклад, різні type можуть запускати різні сценарії в клієнтській програмі.

  • У інтеграціях між сервісами це дозволяє швидко реагувати на певні типи помилок без аналізу тексту.

Приклад коду в іншому сервісі який інтегрується з нашим:

if (problemDetail.getType().equals(URI.create("https://api.example.com/problems/authentication-failed"))) {
    retryAuthentication();
} else if (problemDetail.getType().equals(URI.create("https://api.example.com/problems/invalid-input"))) {
    logInvalidInput();
}

Зрозумілий для користувача інтерфейс

Завдяки структурі, помилки легко локалізувати. Наприклад, title може бути коротким і локалізованим для кінцевого користувача, тоді як detail містить технічну інформацію для розробника.

Приклад локалізації:

{
  "type": "https://api.example.com/problems/authentication-failed",
  "title": "Аутентифікація не вдалася",
  "status": 401,
  "detail": "Облікові дані FIDO2 недійсні.",
  "instance": "/auth/fido2"
}

Спрощений дебагінг і логування

Сервер надає достатньо контексту для розробників, включаючи URI запиту (через поле instance), статус, та інші деталі. Це значно полегшує діагностику проблем.

Розширення без порушення сумісності

Ви можете додавати кастомні поля, не порушуючи стандарту. Наприклад, для інтеграції з платіжним сервісом можна передавати інформацію про специфічні поля:

{
  "type": "https://api.example.com/problems/invalid-payment",
  "title": "Payment Error",
  "status": 400,
  "detail": "The payment method is not supported.",
  "instance": "/payments/456",
  "paymentMethod": "crypto",
  "retryAfter": 3600
}

На фронтенді:

if (error.paymentMethod === "crypto") {
  alert("Please try another payment method.");
} else {
  console.log(`Retry after: ${error.retryAfter} seconds`);
}

Готовність до автоматизації

Завдяки структурованим даним API-інтеграції можуть автоматично реагувати на помилки, наприклад, повторювати запит або повідомляти відповідний відділ підтримки.

if (problemDetail.getStatus() == 429) { // Too Many Requests
    waitAndRetry(problemDetail.getRetryAfter());
}

Висновки

  1. RFC 7807 робить роботу з помилками у вашому API прозорою та зручною.

  2. Замість простих рядків ви отримуєте структуру, яка легко інтегрується в клієнтські додатки.

  3. Реалізація у Spring Boot є простою та дозволяє швидко адаптуватися до стандарту.

Статті про вітчизняний бізнес та цікавих людей:

  • Як модні бренди формують культуру та впливають на глобальні fashion-тренди

    Модні бренди часто стають символами ідентичності. Вони впливають на вибір способу життя не тільки в одязі — розкішні годинники, парфуми, товари для дому та враження підкріплюють культурні наративи успіху, смаку та вишуканості.

    Теми цього довгочиту:

    Мода
  • Створити блог на Друкарні - швидко, легко та безкоштовно

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

    Теми цього довгочиту:

    Друкарня
  • Чому Google Merchant Center може заблокувати обліковий запис?

    Одним з найбільш ефективних каналів продажів є система Google Merchant Center. Правда, акаунт в ній може бути несподівано заблокований, якщо при його налаштуванні були порушені правила системи. У статті розглянемо підводні камені і дамо відповідь як уникнути блокування

    Теми цього довгочиту:

    Google Merchant Center
  • Бухгалтерський супровід ФОП: сучасний підхід до обліку

    Завдяки розвитку інформаційних технологій, впровадженню сучасних рішень і сервісів процес ведення бухобліку бізнесу став значно простішим і зручним. З іншого боку, ті ж технології додали бухгалтерам роботи – з обліком онлайн-продажів і надходжень у валюті, CRM-системами та ін.

    Теми цього довгочиту:

    Бухгалтерський Облік Фоп
  • Пилосос як базова техніка для щоденного прибирання

    Підтримання чистоти в оселі потребує зручних і продуманих рішень, особливо коли йдеться про догляд за різними поверхнями. У домашньому побуті пилосос залишається базовою побутовою технікою, що поєднує сухе та вологе очищення без зайвих зусиль.

    Теми цього довгочиту:

    Пилососи
Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Oleksandr Klymenko
Oleksandr Klymenko@overpathz we.ua/overpathz

Java Software Engineer

39Довгочити
7.6KПрочитання
96Підписники
На Друкарні з 19 квітня

Більше від автора

Це також може зацікавити:

  • Функції max() та min() у Python

    Всіх вітаю! У цій невеличкій статті ми розберемо вбудовані функції min() та max(). Насправді дуже прості суті цих функцій, тож оглянемо кожну з них по черзі.

    Теми цього довгочиту:

    Програмування
  • Метод replace() у Python

    Всіх вітаю! У даній статті ми розберемо вбудований метод для роботи з рядками — метод replace(). У рамках матеріалу ми наведемо три приклади роботи з даним методом та визначимо для себе суть самого метода.

    Теми цього довгочиту:

    Програмування
  • Дві проблеми двофакторної автентифікації ASP.NET Core Identity на основі TOTP

    В ASP.NET Core Identity, при використанні TOTP для 2FA, існують дві ключові проблеми: занадто довге часове вікно для верифікації кодів і відсутність перевірки на їх повторне використання, що підвищує ризик небезпеки.

    Теми цього довгочиту:

    Programming

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Це також може зацікавити:

  • Функції max() та min() у Python

    Всіх вітаю! У цій невеличкій статті ми розберемо вбудовані функції min() та max(). Насправді дуже прості суті цих функцій, тож оглянемо кожну з них по черзі.

    Теми цього довгочиту:

    Програмування
  • Метод replace() у Python

    Всіх вітаю! У даній статті ми розберемо вбудований метод для роботи з рядками — метод replace(). У рамках матеріалу ми наведемо три приклади роботи з даним методом та визначимо для себе суть самого метода.

    Теми цього довгочиту:

    Програмування
  • Дві проблеми двофакторної автентифікації ASP.NET Core Identity на основі TOTP

    В ASP.NET Core Identity, при використанні TOTP для 2FA, існують дві ключові проблеми: занадто довге часове вікно для верифікації кодів і відсутність перевірки на їх повторне використання, що підвищує ризик небезпеки.

    Теми цього довгочиту:

    Programming