# πŸ“€ API Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ² с ΠΊΠ²ΠΎΡ‚Π°ΠΌΠΈ - Вочная докумСнтация ## ΠžΠ±Π·ΠΎΡ€ Quoter прСдоставляСт API для Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ² с систСмой ΠΊΠ²ΠΎΡ‚ ΠΈ автоматичСской ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² ΠΌΠ΅Π΄ΠΈΠ°. ## Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ URL ``` http://localhost:8080 ``` ## АутСнтификация ВсС эндпоинты Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ JWT Ρ‚ΠΎΠΊΠ΅Π½ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅: ``` Authorization: Bearer ``` --- ## πŸ“€ Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Ρ„Π°ΠΉΠ»ΠΎΠ² (УЛУЧШЕННАЯ Π’Π•Π Π‘Π˜Π―) ### POST / Π—Π°Π³Ρ€ΡƒΠΆΠ°Π΅Ρ‚ Ρ„Π°ΠΉΠ»(Ρ‹) Π² S3-совмСстимоС Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ (Storj) с ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½Π½ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ ΠΊΠ²ΠΎΡ‚ ΠΈ Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠ΅ΠΉ. #### Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ запроса ```http Authorization: Bearer Content-Type: multipart/form-data ``` #### ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ - **file** (required) - Ρ„Π°ΠΉΠ»(Ρ‹) для Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ Π² multipart/form-data #### ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ АвтоматичСскоС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ MIME-Ρ‚ΠΈΠΏΠ° ΠΈΠ· содСрТимого Ρ„Π°ΠΉΠ»Π°: - **Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡ**: JPEG, PNG, GIF, WebP, HEIC - **Π’ΠΈΠ΄Π΅ΠΎ**: MP4, WebM, AVI - **Аудио**: MP3, WAV, OGG - **Π”ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Ρ‹**: PDF #### πŸ”„ Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π½Π°Ρ Π»ΠΎΠ³ΠΈΠΊΠ° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ 1. **ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ** - ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ валидация JWT Ρ‚ΠΎΠΊΠ΅Π½Π° 2. **ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΊΠ²ΠΎΡ‚Ρ‹** ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈΠ· Redis 3. **ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΊΠ²ΠΎΡ‚Ρ‹** - ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π½Π΅ достиг Π»ΠΈΠΌΠΈΡ‚Π° 4. **Streaming Ρ‡Ρ‚Π΅Π½ΠΈΠ΅ Ρ„Π°ΠΉΠ»Π°** с ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°ΠΌΠΈ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΌ chunk: - ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π»ΠΈΠΌΠΈΡ‚Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° (500 ΠœΠ‘) - ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΎΠ±Ρ‰Π΅ΠΉ ΠΊΠ²ΠΎΡ‚Ρ‹ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ 5. **ΠŸΡ€ΠΎΠΏΡƒΡΠΊ пустых Ρ„Π°ΠΉΠ»ΠΎΠ²** 6. **ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ MIME-Ρ‚ΠΈΠΏΠ°** ΠΈΠ· содСрТимого (Π½Π΅ ΠΈΠ· Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ!) 7. **ГСнСрация UUID ΠΈΠΌΠ΅Π½ΠΈ** Ρ„Π°ΠΉΠ»Π° с ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΌ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ΠΌ 8. **Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Π² Storj S3** 9. **ОбновлСниС ΠΊΠ²ΠΎΡ‚Ρ‹** ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ 10. **Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΌΠ΅Ρ‚Π°Π΄Π°Π½Π½Ρ‹Ρ…** Π² Redis (с ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ ошибок) #### ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ - **Максимальная ΠΊΠ²ΠΎΡ‚Π° Π½Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ**: 5 Π“Π‘ (5,368,709,120 Π±Π°ΠΉΡ‚) - **ΠœΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°**: 500 ΠœΠ‘ (524,288,000 Π±Π°ΠΉΡ‚) - **ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΊΠ²ΠΎΡ‚Ρ‹ происходит Π²ΠΎ врСмя чтСния** (streaming) - **ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° мноТСствСнных Ρ„Π°ΠΉΠ»ΠΎΠ²** Π² ΠΎΠ΄Π½ΠΎΠΌ запросС #### Π£ΡΠΏΠ΅ΡˆΠ½Ρ‹Π΅ ΠΎΡ‚Π²Π΅Ρ‚Ρ‹ **Один Ρ„Π°ΠΉΠ»:** ```http HTTP/1.1 200 OK Content-Type: text/plain uuid-filename.ext ``` **НСсколько Ρ„Π°ΠΉΠ»ΠΎΠ²:** ```http HTTP/1.1 200 OK Content-Type: application/json { "uploaded_files": ["uuid1.jpg", "uuid2.png"], "count": 2 } ``` #### ΠšΠΎΠ΄Ρ‹ ошибок (Π˜Π‘ΠŸΠ ΠΠ’Π›Π•ΠΠΠ«Π•) | Код | УсловиС | ОписаниС | |-----|---------|----------| | **400 Bad Request** | НСт Ρ„Π°ΠΉΠ»ΠΎΠ² | `"No files provided or all files were empty"` | | **401 Unauthorized** | ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΠ΅Ρ‚ Ρ‚ΠΎΠΊΠ΅Π½ | `"Authorization token required"` | | **401 Unauthorized** | НСвСрный Ρ‚ΠΎΠΊΠ΅Π½ | `"Invalid authorization token"` | | **413 Payload Too Large** | 🎯 ΠŸΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½Π° ΠΊΠ²ΠΎΡ‚Π° | `"Author quota limit exceeded"` | | **413 Payload Too Large** | 🎯 Π‘ΠΎΠ»ΡŒΡˆΠΎΠΉ Ρ„Π°ΠΉΠ» | `"Single file size limit exceeded"` | | **413 Payload Too Large** | 🎯 ΠŸΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΈΠ΅ ΠΏΡ€ΠΈ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ΅ | `"Author quota limit would be exceeded"` | | **415 Unsupported Media Type** | НСподдСрТиваСмый MIME | `"Unsupported file format"` | | **415 Unsupported Media Type** | НСт Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ для MIME | `"Unsupported content type"` | | **500 Internal Server Error** | Ошибка S3 | `"File upload failed"` | | **500 Internal Server Error** | Ошибка ΠΊΠ²ΠΎΡ‚Ρ‹ | `"Failed to update user quota"` | #### βœ… Π˜ΡΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ 1. **ΠŸΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄ ошибки для ΠΊΠ²ΠΎΡ‚Ρ‹**: 413 Payload Too Large 2. **Efficient memory usage**: streaming с ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ°ΠΌΠΈ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΌ chunk 3. **ΠŸΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΊΠ²ΠΎΡ‚Ρ‹** ΠΏΠ΅Ρ€Π΅Π΄ Π½Π°Ρ‡Π°Π»ΠΎΠΌ Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ 4. **Π›ΠΈΠΌΠΈΡ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°**: 500 ΠœΠ‘ 5. **Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π½Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок** с Π΄Π΅Ρ‚Π°Π»ΡŒΠ½Ρ‹ΠΌΠΈ сообщСниями 6. **ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° мноТСствСнных Ρ„Π°ΠΉΠ»ΠΎΠ²** Π² ΠΎΠ΄Π½ΠΎΠΌ запросС 7. **Π”Π΅Ρ‚Π°Π»ΡŒΠ½ΠΎΠ΅ Π»ΠΎΠ³ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅** с ΠΏΡ€ΠΎΡ†Π΅Π½Ρ‚ΠΎΠΌ использования ΠΊΠ²ΠΎΡ‚Ρ‹ --- #### πŸ”„ Как это Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ 1. **JWT Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅** - извлСкаСтся `user_id` ΠΈΠ· Ρ‚ΠΎΠΊΠ΅Π½Π° 2. **Redis lookup** - ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ поиск сСссии ΠΏΠΎ ΠΊΠ»ΡŽΡ‡Ρƒ `session:{user_id}:{token}` 3. **Quota lookup** - ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΊΠ²ΠΎΡ‚Ρ‹ ΠΏΠΎ ΠΊΠ»ΡŽΡ‡Ρƒ `quota:{user_id}` ΠΈΠ· Redis 4. **Activity update** - ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ `last_activity` timestamp (Ссли сСссия Π½Π°ΠΉΠ΄Π΅Π½Π°) 5. **Response building** - объСдинСниС Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈ ΠΊΠ²ΠΎΡ‚Ρ‹ #### Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ запроса ```http Authorization: Bearer ``` #### Π£ΡΠΏΠ΅ΡˆΠ½Ρ‹ΠΉ ΠΎΡ‚Π²Π΅Ρ‚ ```http HTTP/1.1 200 OK Content-Type: application/json { "user_id": "user_12345", "username": "john_doe", "token_type": "session", "created_at": "1642248600", "last_activity": "1642335000", "auth_data": "{\"roles\": [\"user\"], \"permissions\": [...]}", "device_info": "{\"platform\": \"web\", \"browser\": \"Chrome\"}", "quota": { "current_quota": 1073741824, "max_quota": 5368709120, "usage_percentage": 20.0 } } ``` #### Поля ΠΎΡ‚Π²Π΅Ρ‚Π° | ПолС | Π’ΠΈΠΏ | ОписаниС | |------|-----|----------| | `user_id` | string | Π£Π½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ID ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ | | `username` | string \| null | Имя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ | | `token_type` | string \| null | Π’ΠΈΠΏ Ρ‚ΠΎΠΊΠ΅Π½Π° (ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ "session") | | `created_at` | string \| null | Unix timestamp создания сСссии | | `last_activity` | string \| null | Unix timestamp послСднСй активности | | `auth_data` | string \| null | JSON-строка с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ | | `device_info` | string \| null | JSON-строка с ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠ΅ΠΉ ΠΎΠ± устройствС | | `quota.current_quota` | number | Π’Π΅ΠΊΡƒΡ‰Π΅Π΅ использованиС ΠΊΠ²ΠΎΡ‚Ρ‹ Π² Π±Π°ΠΉΡ‚Π°Ρ… | | `quota.max_quota` | number | Максимальная ΠΊΠ²ΠΎΡ‚Π° Π² Π±Π°ΠΉΡ‚Π°Ρ… | | `quota.usage_percentage` | number | ΠŸΡ€ΠΎΡ†Π΅Π½Ρ‚ использования ΠΊΠ²ΠΎΡ‚Ρ‹ | #### ΠšΠΎΠ΄Ρ‹ ошибок | Код | УсловиС | ОписаниС | |-----|---------|----------| | **401 Unauthorized** | ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΠ΅Ρ‚ Ρ‚ΠΎΠΊΠ΅Π½ | `"Authorization token required"` | | **401 Unauthorized** | НСвСрный JWT | `"Invalid or expired session token"` | | **401 Unauthorized** | БСссия Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½Π° | `"Session not found or expired"` | #### ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования ```bash # ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \ http://localhost:8080/ ``` --- ## πŸ“Š Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΠ²ΠΎΡ‚Π°ΠΌΠΈ ### GET /quota ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΊΠ²ΠΎΡ‚Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ. #### ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ запроса ``` GET /quota?user_id= ``` #### ΠžΡ‚Π²Π΅Ρ‚ ```json { "user_id": "user123", "current_quota": 1073741824, "max_quota": 5368709120 } ``` ### POST /quota/increase Π£Π²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΊΠ²ΠΎΡ‚Ρƒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ (admin-only). #### Π’Π΅Π»ΠΎ запроса ```json { "user_id": "user123", "additional_bytes": 1073741824 } ``` #### Валидация - `additional_bytes` Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ > 0 - ВрСбуСтся админский Ρ‚ΠΎΠΊΠ΅Π½ ### POST /quota/set УстанавливаСт Π°Π±ΡΠΎΠ»ΡŽΡ‚Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠ²ΠΎΡ‚Ρ‹ (admin-only). #### Π’Π΅Π»ΠΎ запроса ```json { "user_id": "user123", "new_quota_bytes": 2147483648 } ``` --- ## πŸ” ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ Ρ„Π°ΠΉΠ»ΠΎΠ² ### GET /{filename} Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ„Π°ΠΉΠ» ΠΏΠΎ ΠΈΠΌΠ΅Π½ΠΈ с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½Ρ‹ΠΌΠΈ трансформациями. #### ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ URL - `filename` - имя Ρ„Π°ΠΉΠ»Π° ΠΈΠ»ΠΈ имя_Ρ€Π°Π·ΠΌΠ΅Ρ€.Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΠ΅ для ΠΌΠΈΠ½ΠΈΠ°Ρ‚ΡŽΡ€ #### Query ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ - `s=` - добавляСт ΠΎΠ²Π΅Ρ€Π»Π΅ΠΉ с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ shout (Ρ‚ΠΎΠ»ΡŒΠΊΠΎ изобраТСния) #### ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ```bash GET /uuid-file.jpg # ΠžΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» GET /uuid-file_300.jpg # ΠœΠΈΠ½ΠΈΠ°Ρ‚ΡŽΡ€Π° 300px GET /uuid-file_300.jpg/webp # ΠœΠΈΠ½ΠΈΠ°Ρ‚ΡŽΡ€Π° Π² WebP GET /uuid-file.jpg?s=123 # Π‘ ΠΎΠ²Π΅Ρ€Π»Π΅Π΅ΠΌ shout ``` --- ## πŸ§ͺ ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования ### Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° Ρ„Π°ΠΉΠ»Π° ```bash curl -X POST http://localhost:8080/ \ -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \ -F "file=@photo.jpg" ``` **ΠžΡ‚Π²Π΅Ρ‚ ΠΏΡ€ΠΈ успСхС:** ``` c4ca4238-a0b9-23f1-8429-81dc9bdb9a1f.jpg ``` **ΠžΡ‚Π²Π΅Ρ‚ ΠΏΡ€ΠΈ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΈΠΈ ΠΊΠ²ΠΎΡ‚Ρ‹:** ``` HTTP/1.1 401 Unauthorized Quota exceeded ``` ### ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΊΠ²ΠΎΡ‚Ρ‹ ```bash curl "http://localhost:8080/quota?user_id=user123" \ -H "Authorization: Bearer admin-token" ``` ### Π£Π²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΠ΅ ΠΊΠ²ΠΎΡ‚Ρ‹ (admin) ```bash curl -X POST http://localhost:8080/quota/increase \ -H "Authorization: Bearer admin-token" \ -H "Content-Type: application/json" \ -d '{"user_id": "user123", "additional_bytes": 1073741824}' ``` --- ## πŸ”§ Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΠΈ ΠΏΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡŽ 1. **Π˜ΡΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠ΄ ошибки ΠΊΠ²ΠΎΡ‚Ρ‹**: 401 β†’ 413 2. **Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°** ΠΈΠ· Content-Length 3. **Streaming Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ°** вмСсто ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ чтСния Π² ΠΏΠ°ΠΌΡΡ‚ΡŒ 4. **Π›ΠΈΠΌΠΈΡ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π°** 5. **Π”Π΅Ρ‚Π°Π»ΡŒΠ½Π°Ρ валидация MIME-Ρ‚ΠΈΠΏΠΎΠ²** 6. **ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ использования ΠΊΠ²ΠΎΡ‚** --- *ДокумСнтация Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Π° для вСрсии ΠΊΠΎΠ΄Π° Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ создания. Для ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ см. CHANGELOG.md.*