REST API: Rate limiting, файлы, deprecation
Rate limiting, загрузка файлов и deprecation эндпоинтов REST API.
REST API rate limiting deprecation: 14. Rate limiting
14.1. HTTP-код -- 429 Too Many Requests
REST API rate limiting deprecation — при превышении лимита запросов сервер возвращает 429 с заголовком Retry-After, указывающим через сколько секунд клиент может повторить запрос:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/problem+json
{
"type": "about:blank",
"status": 429,
"title": "Too Many Requests",
"detail": "Превышен лимит запросов. Повторите через 30 секунд.",
"code": "RATE_LIMIT_EXCEEDED"
}
14.2. Заголовки лимитов в каждом ответе
В каждый успешный ответ включаются заголовки, информирующие клиента о текущем состоянии лимитов:
HTTP/1.1 200 OK
RateLimit-Limit: 100
RateLimit-Remaining: 57
RateLimit-Reset: 1719849600
RateLimit-Limit-- максимальное количество запросов в окнеRateLimit-Remaining-- сколько запросов осталось в текущем окнеRateLimit-Reset-- Unix timestamp когда окно сбрасывается
14.3. OpenAPI-описание
В контракте указывать 429 для эндпоинтов с rate limiting:
"429":
description: 'Too Many Requests'
headers:
Retry-After:
schema:
type: integer
description: 'Секунд до сброса лимита'
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
15. Загрузка файлов
15.1. Эндпоинт загрузки
Файлы загружаются как вложенный ресурс через POST с multipart/form-data:
POST /api/v1/documents/{id}/attachments
POST /api/v1/users/me/avatar
15.2. Формат запроса
POST /api/v1/documents/{id}/attachments
Content-Type: multipart/form-data; boundary=----Boundary
------Boundary
Content-Disposition: form-data; name="file"; filename="report.pdf"
Content-Type: application/pdf
<binary data>
------Boundary
Content-Disposition: form-data; name="description"
Отчет за март
------Boundary--
15.3. Ограничения
Ограничения на размер и тип файлов указываются в OpenAPI и документации:
requestBody:
content:
multipart/form-data:
schema:
type: object
required:
- file
properties:
file:
type: string
format: binary
description: 'Файл. Максимум 10 МБ. Допустимые типы: PDF, PNG, JPG'
description:
type: string
maxLength: 500
15.4. Ответ
Код 201 Created. Тело -- метаданные загруженного файла:
{
"attachmentId": "550e8400-e29b-41d4-a716-446655440000",
"fileName": "report.pdf",
"contentType": "application/pdf",
"size": 1048576,
"uploadedAt": "2025-03-15T10:30:00Z"
}
15.5. Скачивание файлов
GET /api/v1/documents/{id}/attachments/{id}
Ответ -- бинарное содержимое файла с соответствующим Content-Type:
HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="report.pdf"
Content-Length: 1048576
<binary data>
16. Deprecation
16.1. Пометка в OpenAPI
Устаревший эндпоинт помечается deprecated: true с указанием альтернативы в description:
/api/v1/orders/{id}/status:
get:
deprecated: true
summary: 'Получить статус заказа'
description: 'DEPRECATED: используйте GET /api/v2/orders/{id}. Будет удалён после 2025-09-01.'
16.2. Заголовок Sunset
Устаревший эндпоинт возвращает заголовок Sunset (RFC 8594) с датой отключения:
HTTP/1.1 200 OK
Sunset: Sat, 01 Sep 2025 00:00:00 GMT
Deprecation: true
Link: </api/v2/orders/{id}>; rel="successor-version"
Sunset-- дата после которой эндпоинт будет удалёнDeprecation: true-- сигнал что эндпоинт устарелLinkсrel="successor-version"-- ссылка на замену
16.3. Процесс вывода из эксплуатации
- Пометить
deprecated: trueв OpenAPI, добавить заголовкиSunsetиDeprecation - Уведомить потребителей (changelog, рассылка, Slack)
- Мониторить трафик на устаревший эндпоинт
- После даты
Sunset-- вернуть410 Gone:
{
"type": "about:blank",
"status": 410,
"title": "Gone",
"detail": "Эндпоинт удалён. Используйте GET /api/v2/orders/{id}.",
"code": "ENDPOINT_REMOVED"
}