<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Александр Нездемина</title><author><name>Александр Нездемина</name></author><id>https://teletype.in/atom/proanalitika</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/proanalitika?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@proanalitika?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=proanalitika"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/proanalitika?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-08-11T01:19:49.548Z</updated><entry><id>proanalitika:3yKc1Pg6eqX</id><link rel="alternate" type="text/html" href="https://teletype.in/@proanalitika/3yKc1Pg6eqX?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=proanalitika"></link><title>Как правильно распределять данные в REST API</title><published>2026-06-16T20:13:47.410Z</published><updated>2026-06-16T20:14:25.630Z</updated><summary type="html">Когда мы проектируем REST API, один из первых практических вопросов звучит так: какие данные куда класть в запросе?</summary><content type="html">
  &lt;p id=&quot;093E&quot;&gt;Когда мы проектируем REST API, один из первых практических вопросов звучит так: &lt;strong&gt;какие данные куда класть в запросе?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;9cHU&quot;&gt;У нас есть путь, query‑параметры, заголовки и тело — и каждый из этих элементов решает свою задачу.&lt;/p&gt;
  &lt;p id=&quot;A3Mh&quot;&gt;В этой статье разберёмся на конкретном кейсе: витрина каталога товаров в мобильном приложении.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;h2 id=&quot;ru5h&quot;&gt;Кейс: витрина каталога и «глупый» фронт&lt;/h2&gt;
  &lt;p id=&quot;Isdb&quot;&gt;Представим, что у нас есть фронт: iOS, Android и мобильный веб.&lt;br /&gt;Фронт максимально &amp;quot;глупый&amp;quot;: он просто ходит в мидл‑сервисы и хочет получить:&lt;/p&gt;
  &lt;ul id=&quot;NXo1&quot;&gt;
    &lt;li id=&quot;UZlM&quot;&gt;витрину с каталогом товаров&lt;/li&gt;
    &lt;li id=&quot;CJKA&quot;&gt;категории товаров&lt;/li&gt;
    &lt;li id=&quot;aKtZ&quot;&gt;корзину пользователя&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;gQCn&quot;&gt;При этом, вместе с запросом фронт передаёт:&lt;/p&gt;
  &lt;ul id=&quot;GMbp&quot;&gt;
    &lt;li id=&quot;dszd&quot;&gt;авторизационный токен&lt;/li&gt;
    &lt;li id=&quot;4zXu&quot;&gt;информацию о приложении (версия, тип устройства, операционная система)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;xWQR&quot;&gt;Задача: &lt;strong&gt;понять, в какую часть HTTP‑запроса какие данные класть, чтобы запросы были логичными, безопасными и удобными для поддержки.&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;SXWR&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;http&quot;&gt;Четыре места для данных в HTTP‑запросе&lt;/h2&gt;
  &lt;p id=&quot;7W7z&quot;&gt;В типичном REST API у нас есть четыре основных &amp;quot;слота&amp;quot;, куда можно положить данные:&lt;/p&gt;
  &lt;ol id=&quot;MFy5&quot;&gt;
    &lt;li id=&quot;WjlR&quot;&gt;Путь (Path) — часть URL, которая описывает, к какому ресурсу мы обращаемся.&lt;/li&gt;
    &lt;li id=&quot;VmSp&quot;&gt;Параметры запроса (Query) — строка после &lt;code&gt;?&lt;/code&gt; в URL, используется для фильтров, сортировок и прочих модификаторов выборки.&lt;/li&gt;
    &lt;li id=&quot;bfcM&quot;&gt;Заголовки (Headers) — метаданные запроса: авторизация, формат данных, информация о клиенте.&lt;/li&gt;
    &lt;li id=&quot;iXlA&quot;&gt;Тело (Body) — основное содержимое: то, что мы создаём, изменяем или отправляем как сложный запрос.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;9XFV&quot;&gt;Дальше разложим наш кейс по этим четырём местам.&lt;/p&gt;
  &lt;p id=&quot;u4wG&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;UFNp&quot;&gt;Авторизационный токен: заголовок Authorization&lt;/h3&gt;
  &lt;p id=&quot;1ZUD&quot;&gt;&lt;strong&gt;Bearer‑токен&lt;/strong&gt; (или любой другой токен авторизации) логичнее всего передавать в заголовке &lt;code&gt;Authorization&lt;/code&gt;.&lt;br /&gt;Это де‑факто стандарт для REST API и рекомендованный способ передачи авторизационных данных.&lt;/p&gt;
  &lt;pre id=&quot;994l&quot;&gt;GET /api/v1/products
Authorization: Bearer eyJhbGciOiJIUz...&lt;/pre&gt;
  &lt;p id=&quot;FLop&quot;&gt;Почему именно заголовок:&lt;/p&gt;
  &lt;ul id=&quot;dkJ8&quot;&gt;
    &lt;li id=&quot;ErPf&quot;&gt;токен не попадает в URL, а значит — не засветится в истории браузера или прокси&lt;/li&gt;
    &lt;li id=&quot;old7&quot;&gt;многие инструменты и библиотеки по умолчанию ожидают токен именно в &lt;code&gt;Authorization&lt;/code&gt;&lt;/li&gt;
    &lt;li id=&quot;BqUw&quot;&gt;это согласуется с практиками OAuth 2.0 и большинством публичных API&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;ttbL&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;2ZEE&quot;&gt;Метаданные клиента: тип приложения, версия, ОС&lt;/h3&gt;
  &lt;p id=&quot;FAvi&quot;&gt;Информация о том кто обращается, мобилка, веб.  Это &lt;strong&gt;метаданные&lt;/strong&gt;: они описывают не ресурс, а того, &lt;em&gt;кто&lt;/em&gt; делает запрос.&lt;br /&gt;Примеры:&lt;/p&gt;
  &lt;ul id=&quot;QHoR&quot;&gt;
    &lt;li id=&quot;REpG&quot;&gt;тип приложения (mobile/web)&lt;/li&gt;
    &lt;li id=&quot;87vV&quot;&gt;версия приложения&lt;/li&gt;
    &lt;li id=&quot;qdrX&quot;&gt;операционная система и её версия&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;LlJz&quot;&gt;Эти данные нужны серверу, чтобы:&lt;/p&gt;
  &lt;ul id=&quot;lpJ7&quot;&gt;
    &lt;li id=&quot;bFBb&quot;&gt;принимать решения по фичефлагам (например, отключать функциональность для старых версий)&lt;/li&gt;
    &lt;li id=&quot;12cN&quot;&gt;логировать и анализировать трафик по типам клиентов&lt;/li&gt;
    &lt;li id=&quot;UXH8&quot;&gt;внедрять ограничения: «для версии ниже 1.5 не отдаём новый тип карточек товара»&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;4WB3&quot;&gt;Так как эти данные нужны &lt;strong&gt;при любом запросе&lt;/strong&gt;, а не только при конкретных методах, логично передавать их в заголовках.&lt;/p&gt;
  &lt;p id=&quot;Eskq&quot;&gt;Пример:&lt;/p&gt;
  &lt;pre id=&quot;VESp&quot;&gt;X-App-Type: ios
X-App-Version: 1.2.3
X-OS-Name: iOS
X-OS-Version: 16.4&lt;/pre&gt;
  &lt;p id=&quot;IY7h&quot;&gt;Исторически было принято использовать префикс &lt;code&gt;X-&lt;/code&gt; для кастомных заголовков, но сейчас его применение считается устаревшей практикой.&lt;br /&gt;Можно использовать более нейтральные варианты, например: &lt;code&gt;App-Type&lt;/code&gt;, &lt;code&gt;App-Version&lt;/code&gt;, &lt;code&gt;Client-OS-Name&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;HLet&quot;&gt;Ключевой момент: &lt;strong&gt;не класть эти метаданные в тело&lt;/strong&gt;, потому что:&lt;/p&gt;
  &lt;ul id=&quot;iIzD&quot;&gt;
    &lt;li id=&quot;aPhx&quot;&gt;у GET‑запросов тела обычно нет, а метаданные нам нужны и там&lt;/li&gt;
    &lt;li id=&quot;TfmE&quot;&gt;нам важна предсказуемость: любой запрос несёт одни и те же заголовки клиента&lt;/li&gt;
    &lt;li id=&quot;SqIR&quot;&gt;прокси и кэширующие слои чаще учитывают заголовки, чем тело, для принятия решений&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;x3Uw&quot;&gt;Фильтры и сортировка: параметры запроса (query)&lt;/h3&gt;
  &lt;p id=&quot;p9YH&quot;&gt;Когда речь идёт о &lt;strong&gt;фильтрации&lt;/strong&gt;, &lt;strong&gt;поиске&lt;/strong&gt; или &lt;strong&gt;сортировке&lt;/strong&gt;, первый кандидат — &lt;strong&gt;query‑параметры&lt;/strong&gt;.&lt;br /&gt;Они позволяют явно описать, какую выборку мы хотим получить.&lt;/p&gt;
  &lt;p id=&quot;pvr2&quot;&gt;Пример запроса витрины:&lt;/p&gt;
  &lt;pre id=&quot;KEle&quot;&gt;GET /api/v1/products?sort=price&amp;amp;category=electronics&amp;amp;page=1&amp;amp;limit=20&lt;/pre&gt;
  &lt;p id=&quot;zx0w&quot;&gt;Здесь:&lt;/p&gt;
  &lt;ul id=&quot;zV59&quot;&gt;
    &lt;li id=&quot;gIkP&quot;&gt;&lt;code&gt;sort=price&lt;/code&gt; — сортировка по цене&lt;/li&gt;
    &lt;li id=&quot;XRq5&quot;&gt;&lt;code&gt;category=electronics&lt;/code&gt; — фильтрация по категории&lt;/li&gt;
    &lt;li id=&quot;HnQ6&quot;&gt;&lt;code&gt;page&lt;/code&gt; и &lt;code&gt;limit&lt;/code&gt; — параметры пагинации&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;fGjg&quot;&gt;Рекомендации по фильтрам через query:&lt;/p&gt;
  &lt;ul id=&quot;J1Za&quot;&gt;
    &lt;li id=&quot;0dHp&quot;&gt;использовать понятные названия (&lt;code&gt;price&lt;/code&gt;, &lt;code&gt;category&lt;/code&gt;, &lt;code&gt;brand&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;)&lt;/li&gt;
    &lt;li id=&quot;C9Bw&quot;&gt;делать параметры консистентными: например, &lt;code&gt;page&lt;/code&gt;/&lt;code&gt;limit&lt;/code&gt; везде, а не &lt;code&gt;page&lt;/code&gt;/&lt;code&gt;perPage&lt;/code&gt; в одном методе и &lt;code&gt;offset&lt;/code&gt;/&lt;code&gt;count&lt;/code&gt; в другом.&lt;/li&gt;
    &lt;li id=&quot;XNon&quot;&gt;для сложных фильтров применять единый формат (например, &lt;code&gt;filter[field]=value&lt;/code&gt; или &lt;code&gt;filter=field:op:value&lt;/code&gt;)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;N9O7&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;EDMW&quot;&gt;Когда фильтры уходят в тело запроса&lt;/h3&gt;
  &lt;p id=&quot;O4Tc&quot;&gt;Бывает, что фильтрация становится настолько сложной, что query‑строка становится:&lt;/p&gt;
  &lt;ul id=&quot;v0IG&quot;&gt;
    &lt;li id=&quot;Rkkf&quot;&gt;слишком длинной&lt;/li&gt;
    &lt;li id=&quot;DkH9&quot;&gt;с трудом читаемой&lt;/li&gt;
    &lt;li id=&quot;3nf8&quot;&gt;плохо валидируемой и документируемой&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Zsk0&quot;&gt;В таких случаях разумно &lt;strong&gt;перенести фильтры в тело запроса&lt;/strong&gt; и использовать &lt;code&gt;POST&lt;/code&gt; для получения данных по сложному запросу.&lt;/p&gt;
  &lt;pre id=&quot;EyOn&quot;&gt;POST /api/v1/products/search
Content-Type: application/json

{
  &amp;quot;sort&amp;quot;: { &amp;quot;field&amp;quot;: &amp;quot;price&amp;quot;, &amp;quot;direction&amp;quot;: &amp;quot;asc&amp;quot; },
  &amp;quot;filters&amp;quot;: {
    &amp;quot;category&amp;quot;: [&amp;quot;electronics&amp;quot;, &amp;quot;appliances&amp;quot;],
    &amp;quot;price&amp;quot;: { &amp;quot;gte&amp;quot;: 1000, &amp;quot;lte&amp;quot;: 5000 },
    &amp;quot;inStock&amp;quot;: true
  },
  &amp;quot;page&amp;quot;: 1,
  &amp;quot;limit&amp;quot;: 20
}&lt;/pre&gt;
  &lt;p id=&quot;fwTh&quot;&gt;Такой подход встречается, когда нужны:&lt;/p&gt;
  &lt;ul id=&quot;zwff&quot;&gt;
    &lt;li id=&quot;ZF5v&quot;&gt;сложные комбинированные фильтры&lt;/li&gt;
    &lt;li id=&quot;CaWe&quot;&gt;вложенные структуры&lt;/li&gt;
    &lt;li id=&quot;Z4ta&quot;&gt;массивы значений и сложные условия&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;zOfE&quot;&gt;Правило, которое удобно держать в голове:&lt;br /&gt;&lt;strong&gt;простые фильтры — в query, сложные и структурированные — в теле запроса.&lt;/strong&gt;&lt;/p&gt;
  &lt;h3 id=&quot;SGK9&quot;&gt;&lt;/h3&gt;
  &lt;p id=&quot;9nji&quot;&gt;И финальное, все данные, которые мы получаем о товарах мы забираем из тела запроса. &lt;/p&gt;

</content></entry><entry><id>proanalitika:5Y-SWcSDysw</id><link rel="alternate" type="text/html" href="https://teletype.in/@proanalitika/5Y-SWcSDysw?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=proanalitika"></link><title>Как правильно оформлять коды ошибок в API</title><published>2026-06-06T20:59:30.248Z</published><updated>2026-07-02T14:08:23.246Z</updated><summary type="html">Ошибка в API — это не просто «что-то пошло не так». Для нормальной интеграции важно, чтобы ошибка была предсказуемой, однозначной и удобной для обработки и людьми, и программам.</summary><content type="html">
  &lt;p id=&quot;eN3y&quot;&gt;Если мы говорим про проектирование, то аналитики часто продумывают формат запроса и ответа API, но забывают о том, как должны выглядеть ошибки. Часто это происходит потому, что в компании уже принят какой-то стандарт, и все привыкают работать по накатанной. Такой подход хорошо работает в устоявшихся проектах, но если у вас новый проект, лучше самостоятельно продумать ответ на случай, если что-то пойдёт не так. Ведь ошибки — это часть контракта, и если вы не дадите конкретики, разработчики сделают так, как им кажется правильным.&lt;/p&gt;
  &lt;h2 id=&quot;suK9&quot;&gt;&lt;br /&gt;Из чего состоит хорошая ошибка?&lt;/h2&gt;
  &lt;p id=&quot;JiSI&quot;&gt;Любая ошибка должна отвечать на три вопроса: что произошло, почему и что с этим делать. &lt;/p&gt;
  &lt;p id=&quot;arlt&quot;&gt;Пройдёмся по этим пунктам.&lt;/p&gt;
  &lt;h3 id=&quot;j8xV&quot;&gt;Что произошло?&lt;/h3&gt;
  &lt;p id=&quot;nYWK&quot;&gt;Ответ на этот вопрос обычно закрывают коды ответов 4xx и 5xx. &lt;br /&gt;Например: &lt;br /&gt;400 Bad Request — некорректные данные от клиента; &lt;br /&gt;401 Unauthorized — пользователь не аутентифицирован (нет токена или он недействителен); &lt;br /&gt;403 Forbidden — аутентификация есть, но нет прав доступа; &lt;br /&gt;404 Not Found — ресурс не найден; &lt;br /&gt;409 Conflict — конфликт состояния (например, такой email уже зарегистрирован); &lt;br /&gt;422 Unprocessable Entity — данные приняты, но не прошли бизнес-валидацию; &lt;br /&gt;429 Too Many Requests — превышен лимит запросов; &lt;br /&gt;500 Internal Server Error — ошибка на стороне сервера; &lt;br /&gt;503 Service Unavailable — сервис временно недоступен.&lt;br /&gt;&lt;br /&gt;Но достаточно ли этого? В некоторых кейсах да, но иногда лучше вместе с кодом отправлять в теле ответа мнемонику, например: USER_NOT_FOUND, VALIDATION_ERROR, DUPLICATE_ORDER. Если это указать, клиенту будет проще разобраться и сделать обработку более персонализированной&lt;/p&gt;
  &lt;h3 id=&quot;4ZWa&quot;&gt;Почему это произошло?&lt;/h3&gt;
  &lt;p id=&quot;H6j0&quot;&gt;Частая ситуация: клиент получает ошибку, но, чтобы понять реальную причину, приходится лезть в логи и вручную разбираться. Поэтому лучше сразу дать пояснение. Для этого в ответ, помимо мнемоники, добавляют поле message с понятным описанием проблемы. В него не стоит включать технические трейсы или детали, которые не будут понятны пользователю. &lt;/p&gt;
  &lt;h3 id=&quot;2on6&quot;&gt;Что с этим делать?&lt;/h3&gt;
  &lt;p id=&quot;OKy3&quot;&gt;В идеале — добавить инструкцию по исправлению ошибки. Например: «повторить запрос через N секунд», «исправить данные», «обратиться в поддержку». Иногда даже передают номер телефона или другие контакты поддержки.&lt;/p&gt;
  &lt;p id=&quot;s87X&quot;&gt;&lt;br /&gt;В теории всё звучит хорошо. Теперь давай разберёмся, как это реализовать и как может выглядеть такой ответ.&lt;/p&gt;
  &lt;p id=&quot;fLjZ&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;m7Fq&quot;&gt;Структура тела ошибки&lt;/h2&gt;
  &lt;p id=&quot;mKEn&quot;&gt;Если ошибки во всех эндпоинтах выглядят одинаково, клиентам проще писать обработчики. Именно поэтому лучше использовать единый формат.&lt;br /&gt;&lt;br /&gt;Хороший базовый формат тела ошибки:&lt;/p&gt;
  &lt;pre id=&quot;h1AF&quot;&gt;{
  &amp;quot;code&amp;quot;: &amp;quot;VALIDATION_ERROR&amp;quot;,
  &amp;quot;message&amp;quot;: &amp;quot;Ошибка валидации&amp;quot;,
  &amp;quot;errors&amp;quot;: [
    {
      &amp;quot;field&amp;quot;: &amp;quot;email&amp;quot;,
      &amp;quot;code&amp;quot;: &amp;quot;INVALID_FORMAT&amp;quot;,
      &amp;quot;message&amp;quot;: &amp;quot;Неправильный формат email&amp;quot;
    }
  ]
}&lt;/pre&gt;
  &lt;p id=&quot;oTsL&quot;&gt;code — машиночитаемая мнемоника, по которой клиент понимает, что делать.&lt;br /&gt;message — человекочитаемое описание ошибки.&lt;br /&gt;errors — массив, позволяющий вернуть все проблемы валидации за один запрос, а не по одной. Это особенно важно для форм, но лучше, чтобы контракт был единым для всех эндпоинтов.&lt;/p&gt;
  &lt;p id=&quot;kYwd&quot;&gt;Иногда вместо errors, если API простое и не требует детальной валидации, добавляют поле details или messageDetails, чтобы описать, как исправить ситуацию:&lt;/p&gt;
  &lt;pre id=&quot;FI1M&quot;&gt;{  
 &amp;quot;code&amp;quot;: &amp;quot;DUPLICATE_ORDER&amp;quot;,  
 &amp;quot;message&amp;quot;: &amp;quot;Заказ с id 12345 уже существует&amp;quot;,  
 &amp;quot;messageDetails&amp;quot;: &amp;quot;Заказ с номером 12345 уже существует. Если это ошибка, напишите в чат поддержки&amp;quot; 
}&lt;/pre&gt;
  &lt;p id=&quot;hWG0&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;N88q&quot;&gt;Еще один хороший паттерн — добавлять идентификатор запроса, чтобы можно было отследить всю цепочку вызовов. Обычно его передают в поле traceId или correlationId.&lt;/p&gt;
  &lt;pre id=&quot;pFwS&quot;&gt;{  
 &amp;quot;code&amp;quot;: &amp;quot;DUPLICATE_ORDER&amp;quot;,  
 &amp;quot;message&amp;quot;: &amp;quot;Заказ с id 12345 уже существует&amp;quot;,  
 &amp;quot;traceId&amp;quot;: &amp;quot;abc-123-xyz&amp;quot; 
}&lt;/pre&gt;
  &lt;p id=&quot;Gw3r&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;8etR&quot;&gt;Частые антипаттерны, которые я встречаю на практике&lt;/h2&gt;
  &lt;p id=&quot;RQRJ&quot;&gt;1)Отвечать HTTP-кодом 200 на любые ответы, а реальный код ошибки передавать в теле ответа. Например:&lt;/p&gt;
  &lt;pre id=&quot;eo1I&quot;&gt;{
 &amp;quot;code&amp;quot;: &amp;quot;404&amp;quot;,
 &amp;quot;message&amp;quot;: &amp;quot;NOT FOUND&amp;quot;
}&lt;/pre&gt;
  &lt;p id=&quot;kPST&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;zgm2&quot;&gt;2) Использовать разные форматы ошибок в разных эндпоинтах. В одном месте {&amp;quot;error&amp;quot;: &amp;quot;...&amp;quot;}, в другом {&amp;quot;message&amp;quot;: &amp;quot;...&amp;quot;}. В этом случае клиенту или сервису, который с вами интегрируется, придётся делать отдельный парсер для каждого варианта ошибки и затем унифицировать их.&lt;/p&gt;
  &lt;p id=&quot;09zg&quot;&gt;3) Передавать стандартные сообщения вроде «что-то пошло не так» или технические ошибки типа NullPointerException в message. Такой формат не даёт никакой полезной информации. &lt;br /&gt;&lt;/p&gt;
  &lt;h2 id=&quot;KrvN&quot;&gt;Что фиксировать в требованиях при проектировании API&lt;/h2&gt;
  &lt;ul id=&quot;8ikc&quot;&gt;
    &lt;li id=&quot;NDiS&quot;&gt;HTTP-статус должен соответствовать типу ошибки, а не всегда быть 200.&lt;/li&gt;
    &lt;li id=&quot;ve1r&quot;&gt;Указывать поле code с машиночитаемой мнемоникой.&lt;/li&gt;
    &lt;li id=&quot;T0DD&quot;&gt;Добавлять поле message без внутренних деталей и стек-трейсов.&lt;/li&gt;
    &lt;li id=&quot;a2Fq&quot;&gt;Делать единый формат ошибки во всех эндпоинтах.&lt;/li&gt;
    &lt;li id=&quot;zHxQ&quot;&gt;Если есть валидация, возвращать массив ошибок с описанием всех проблем, а не по одной.&lt;br /&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;LXub&quot;&gt;И ключевое&lt;/h2&gt;
  &lt;p id=&quot;9fKY&quot;&gt;Помните, что плохо спроектированные ответы об ошибках могут усложнить работу вам и вашей команде. Из-за этого можно потратить много часов на дебаг и разбор обращений от поддержки. При этом, если в команде или компании уже есть принятый формат, не стоит его ломать. Лучше сначала разобраться, почему он устроен именно так и какие ограничения за этим стоят.&lt;/p&gt;

</content></entry><entry><id>proanalitika:lu_GijFBCIK</id><link rel="alternate" type="text/html" href="https://teletype.in/@proanalitika/lu_GijFBCIK?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=proanalitika"></link><title>Как использовать метод DELETE так, чтобы не получить по шапке?</title><published>2026-02-17T13:22:23.977Z</published><updated>2026-02-17T13:22:23.977Z</updated><summary type="html">Метод DELETE под собой БАЗОВО подразумевает, что вызвав его - мы удалим полностью данные.</summary><content type="html">
  &lt;p id=&quot;Bn43&quot;&gt;&lt;strong&gt;Метод DELETE&lt;/strong&gt; под собой &lt;strong&gt;БАЗОВО&lt;/strong&gt; подразумевает, что вызвав его - мы &lt;strong&gt;удалим полностью данные&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;96V7&quot;&gt;Но что делать, если есть сомнение: &lt;strong&gt;&lt;em&gt;а действительно ли надо удалять ресурс? Может его надо обновить и просто скрыть без удаления, вдруг понадобится?&lt;br /&gt;&lt;br /&gt;&lt;/em&gt;&lt;/strong&gt;Если такой вопрос возникает, значит нам надо понять как действовать, потому что если мы неправильно спроектируем взаимодействие и удалим данные, которые нужны на самом деле, то есть большой риск, что компания получит убытки, а вы по шапке.&lt;br /&gt;Приведу примеры на нескольких кейсах.&lt;br /&gt;&lt;/p&gt;
  &lt;h3 id=&quot;jat3&quot;&gt;&lt;strong&gt;Кейс 1️⃣.  Удаление банковской транзакции&lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;2bPU&quot;&gt;Вы совершили отложенный перевод денежных средств в банк клиенте. Заявка в статусе на отправку, но деньги еще не ушли и вы хотите ее удалить.&lt;/p&gt;
  &lt;p id=&quot;vs07&quot;&gt;&lt;strong&gt;Что делать?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;apaR&quot;&gt;Если мы просто удалим заявку на денежный перевод и она не ушла, то наверное ничего страшного, однако, это финансовая операция и поэтому у нее должен быть жесткий учет, значит DELETE в данном случае использовать нельзя.&lt;/p&gt;
  &lt;p id=&quot;20VV&quot;&gt;➡️ можно сделать SOFT DELETE и просто прокинуть статус disable, а лучше поменять статус на &amp;quot;отменена&amp;quot; и тогда сохранится историчность.&lt;/p&gt;
  &lt;p id=&quot;xIlr&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;A4u8&quot;&gt;&lt;strong&gt;Кейс 2️⃣. Удаление товара из системы в интернет-магазине.&lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;mOEu&quot;&gt;У вас есть справочник товаров, которым управляют сотрудники. Они могут добавлять товары и удалять.&lt;/p&gt;
  &lt;p id=&quot;DDxO&quot;&gt;У вас есть старые товары, которые уже перестали продаваться в магазине. Сотрудник хочет их удалить.&lt;/p&gt;
  &lt;p id=&quot;VkjR&quot;&gt;&lt;strong&gt;Что делать?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;xgAk&quot;&gt;Тут у нас двоякая ситуация, потому что с одной стороны, товар уже не используется, но не факт что он не использовался раньше, и отсутствует в заказах, поэтому здесь можно пойти таким путем:&lt;/p&gt;
  &lt;p id=&quot;CapI&quot;&gt;Мы проверяем, был ли товар добавлен хотя бы в 1 заказ.&lt;/p&gt;
  &lt;p id=&quot;MmvX&quot;&gt;➡️ Если был, то удалять такой товар нельзя и его нужно архивировать, так как, если мы его удалим, у нас умрут связи и это повлияет не только на историю заказов, но может затронуть финансовые операции, расчеты, а это очень больно, уж поверьте. Используем SOFT DELETE.&lt;/p&gt;
  &lt;p id=&quot;iET6&quot;&gt;➡️ Если товар ни с чем не связан, то спокойно делаем DELETE.&lt;/p&gt;
  &lt;p id=&quot;ZiyL&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;p8XP&quot;&gt;&lt;strong&gt;Кейс 3️⃣. Удаление учётной записи пользователя в интернет-магазине&lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;FxhC&quot;&gt;У вас есть учетная запись и функциональность по удалению этой учетки. Как ее реализовать?&lt;/p&gt;
  &lt;p id=&quot;k8t4&quot;&gt;Тут как и в предыдущем пункте - два варианта:&lt;/p&gt;
  &lt;p id=&quot;a9bL&quot;&gt;➡️ Если у пользователя не было покупок → можно удалить его аккаунт так:&lt;/p&gt;
  &lt;pre id=&quot;Nn8T&quot;&gt;DELETE /users/{id}&lt;/pre&gt;
  &lt;p id=&quot;Qc0N&quot;&gt;➡️ Если он совершал заказы → удалять нельзя, потому что его данные связаны с чеками, гарантиями, возвратами, заказами.&lt;/p&gt;
  &lt;p id=&quot;Zw7Z&quot;&gt;Но если бы я реализовывал именно этот кейс, то не закладывал бы сложную логику, потому что я не люблю усложнять. Сделать бы так:&lt;/p&gt;
  &lt;p id=&quot;C8y5&quot;&gt;➡️ во всех случаях, когда Клиент удаляет учетку, я бы делал &lt;strong&gt;SOFT DELETE&lt;/strong&gt; и еще добавил бы анонимность данных.&lt;/p&gt;
  &lt;p id=&quot;km9l&quot;&gt;➖➖➖&lt;/p&gt;
  &lt;p id=&quot;RbEF&quot;&gt;А дальше дело техники&lt;/p&gt;
  &lt;p id=&quot;6dDl&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;jTWT&quot;&gt;Как оформить запрос при &lt;strong&gt;DELETE и SOFT DELETE?&lt;/strong&gt;&lt;/h2&gt;
  &lt;h3 id=&quot;7lqO&quot;&gt;&lt;strong&gt;«Полное» удаление&lt;/strong&gt; &lt;strong&gt;(DELETE)&lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;GmaU&quot;&gt;• &lt;strong&gt;Метод&lt;/strong&gt;: DELETE&lt;/p&gt;
  &lt;p id=&quot;XqkH&quot;&gt;• &lt;strong&gt;Endpoint&lt;/strong&gt;: /resource/{id}&lt;br /&gt;&lt;/p&gt;
  &lt;h3 id=&quot;oCMx&quot;&gt;&lt;strong&gt;«Мягкое» удаление (SOFT DELETE)&lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;CNrP&quot;&gt;• &lt;strong&gt;Метод&lt;/strong&gt;: чаще PATCH или PUT&lt;/p&gt;
  &lt;p id=&quot;WG5M&quot;&gt;• &lt;strong&gt;Endpoint&lt;/strong&gt;: resource/{id}, где передаём значение поля is_deleted = true или archived = true или status = &amp;quot;cancelled&amp;quot;.&lt;/p&gt;
  &lt;p id=&quot;rvOV&quot;&gt;Пример:&lt;/p&gt;
  &lt;pre id=&quot;bacd&quot;&gt;PATCH /api/v1/products/123

Headers:
Content-Type: application/json

Body:
{
&amp;quot;is_archived&amp;quot;: true,
&amp;quot;archived_at&amp;quot;: &amp;quot;2025-02-26T12:00:00Z&amp;quot;
}&lt;/pre&gt;
  &lt;p id=&quot;8tMi&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;90zf&quot;&gt;Почему при SOFT DELETE мы не используем метод DELETE?&lt;/h2&gt;
  &lt;p id=&quot;he1b&quot;&gt;В целом, мы можем делать и soft delete и обычное удаление через метод DELETE, но в этом случае такой запрос не очевидно читается. И внутри придется делать дополнительную логику. &lt;br /&gt;&lt;br /&gt;⚡️⚡️⚡️&lt;/p&gt;
  &lt;p id=&quot;ZFQF&quot;&gt;Не важно через какой метод вы это делаете, важно лишь то, что вы понимаете БАЗОВЫЕ принципы и  логику, а еще используете мышление системного аналитика для решения таких задач.&lt;/p&gt;

</content></entry><entry><id>proanalitika:KqnkMgBIYqi</id><link rel="alternate" type="text/html" href="https://teletype.in/@proanalitika/KqnkMgBIYqi?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=proanalitika"></link><title>Как правильно описать USE CASES, когда описываешь спеку на разработку UI интерфейса, чтобы команда не приходила потом с 1000 вопросов потом?</title><published>2025-05-21T07:36:36.605Z</published><updated>2025-05-21T07:37:49.973Z</updated><summary type="html">Предлагаю сразу на примере:</summary><content type="html">
  &lt;p id=&quot;YZCJ&quot;&gt;Предлагаю сразу на примере:&lt;/p&gt;
  &lt;p id=&quot;TFCN&quot;&gt;У нас есть трекер калорий и него есть классная фича- сканирование штрих-кода для автозаполнения КБЖУ.&lt;/p&gt;
  &lt;p id=&quot;PYTR&quot;&gt;Данные по штрих-кодам мы получаем из нескольких источников внешней системы, но агригируем все у себя на бэке.&lt;/p&gt;
  &lt;p id=&quot;M0OI&quot;&gt;Тебе &lt;strong&gt;поставили задачу - описать требования к UI. &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;jGIf&quot;&gt;И один из способов это сделать –  использовать USE CASES&lt;/p&gt;
  &lt;p id=&quot;Mt4u&quot;&gt;Классически USE CASE выглядит так:&lt;/p&gt;
  &lt;p id=&quot;6Dpo&quot;&gt;✔️ Название,&lt;/p&gt;
  &lt;p id=&quot;8SXb&quot;&gt;✔️ Актёры,&lt;/p&gt;
  &lt;p id=&quot;kkyS&quot;&gt;✔️ Предусловия,&lt;/p&gt;
  &lt;p id=&quot;aJ6j&quot;&gt;✔️ Основной сценарий,&lt;/p&gt;
  &lt;p id=&quot;tOdC&quot;&gt;✔️ Альтернативные/ошибочные потоки,&lt;/p&gt;
  &lt;p id=&quot;Vk6u&quot;&gt;✔️ Результат.&lt;/p&gt;
  &lt;p id=&quot;Xpgv&quot;&gt;Теперь применяем это к нашему примеру:&lt;/p&gt;
  &lt;p id=&quot;ouox&quot;&gt;✔️ &lt;strong&gt;Название&lt;/strong&gt;:&lt;/p&gt;
  &lt;p id=&quot;SXFZ&quot;&gt;UC‑1 Быстрое добавление продукта по штрих‑коду&lt;/p&gt;
  &lt;p id=&quot;cogJ&quot;&gt;✔️ &lt;strong&gt;Основной актёр&lt;/strong&gt;:&lt;/p&gt;
  &lt;p id=&quot;K2rc&quot;&gt;Пользователь приложения&lt;/p&gt;
  &lt;p id=&quot;5niQ&quot;&gt;&lt;strong&gt;Системы&lt;/strong&gt;:&lt;/p&gt;
  &lt;p id=&quot;OpJC&quot;&gt;Мобильное приложение, Back-сервис.&lt;/p&gt;
  &lt;p id=&quot;dJdP&quot;&gt;✔️ &lt;strong&gt;Предусловия&lt;/strong&gt;:&lt;/p&gt;
  &lt;p id=&quot;rmOJ&quot;&gt;- Приложение получило разрешение на доступ к камере.&lt;/p&gt;
  &lt;p id=&quot;uOHw&quot;&gt;- Устройство подключено к интернету.&lt;/p&gt;
  &lt;p id=&quot;ao6X&quot;&gt;✔️ &lt;strong&gt;Основной сценарий:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;NPDa&quot;&gt;1. Пользователь открывает экран «Добавить продукт» и нажимает «Сканер штрих‑кода»;&lt;/p&gt;
  &lt;p id=&quot;tzJN&quot;&gt;2. Камера считывает шрих-код и отправляет POST /barcode/scan {code} на Backend;&lt;/p&gt;
  &lt;p id=&quot;5hri&quot;&gt;3. Backend ищет у себя в кэше.&lt;/p&gt;
  &lt;p id=&quot;Uwre&quot;&gt;- Если найден, возвращает нутриенты и калории.&lt;/p&gt;
  &lt;p id=&quot;EfEn&quot;&gt;- Если не найден, то идет во внешних API.&lt;/p&gt;
  &lt;p id=&quot;Z7Kq&quot;&gt;4. API отвечает 200 OK, Backend нормализует данные, рассчитывает калории по формуле, кладёт результат в кэш.&lt;/p&gt;
  &lt;p id=&quot;o9jW&quot;&gt;5. Приложение показывает карточку продукта с БЖУ и кнопкой «Добавить в дневник».&lt;/p&gt;
  &lt;p id=&quot;ovR2&quot;&gt;✔️ &lt;strong&gt;Альтернативы:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;y6fA&quot;&gt;2А. Камера не запустилась — приложение предлагает ввести код вручную;&lt;/p&gt;
  &lt;p id=&quot;kbWy&quot;&gt;3А. Внешний API вернул 404 — открывается форма ручного ввода нутриентов;&lt;/p&gt;
  &lt;p id=&quot;438p&quot;&gt;3B. API отвалилась по таймауту — показывается заглушка «Сервис недоступен», предлагается сфотографировать этикетку;&lt;/p&gt;
  &lt;p id=&quot;tV4e&quot;&gt;✔️ &lt;strong&gt;Постусловия:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;x2Pg&quot;&gt;- При успешном сценарии - продукт сохранён в дневнике, данные кэшированы;&lt;/p&gt;
  &lt;p id=&quot;HKsV&quot;&gt;- При ошибках пользователь получил понятный способ продолжить.&lt;/p&gt;
  &lt;p id=&quot;r79a&quot;&gt;➖➖➖&lt;/p&gt;
  &lt;p id=&quot;XjeF&quot;&gt;&lt;strong&gt;Такой подход&lt;/strong&gt; к описанию постановки &lt;strong&gt;можно найти в Гугл, &lt;/strong&gt;когда ты пытаешься экстренно разобраться, как решить задачу, которую перед тобой поставили, а ты не понимаешь с чего начать, а он предательски тебе выдал &amp;quot;вот классный способ постановки&amp;quot;.&lt;/p&gt;
  &lt;p id=&quot;KyCq&quot;&gt;➖➖➖&lt;/p&gt;
  &lt;p id=&quot;I77N&quot;&gt;Но &lt;strong&gt;что в этом подходе не так? &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;iRBJ&quot;&gt;❗️А то, что front разработчику вообще не нужно знать, что происходит на стороне back, а back разработчику может и важно, что там делает фронт, но скорее нет = &lt;strong&gt;ИЗБЫТОЧНОСТЬ, которая и порождает за собой лишние вопросы со стороны команды. &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;B3Xh&quot;&gt;➖➖➖&lt;/p&gt;
  &lt;p id=&quot;Olbb&quot;&gt;Так &lt;strong&gt;что&lt;/strong&gt; же &lt;strong&gt;важно&lt;/strong&gt;, &lt;strong&gt;когда&lt;/strong&gt; мы &lt;strong&gt;описываем UI&lt;/strong&gt;?&lt;/p&gt;
  &lt;p id=&quot;KTCv&quot;&gt;❗️&lt;strong&gt;Я в своей практике использую такой подход: разбиваю USE CASE на шаги и расписываю отдельно действия пользователя, и отдельно - системы, в рамках одного шага. &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;1vJS&quot;&gt;Вернемся к нашему примеру,&lt;/p&gt;
  &lt;p id=&quot;Hxyu&quot;&gt;✔️ &lt;strong&gt;Название:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;ypwp&quot;&gt;UC‑1 Быстрое добавление продукта по штрих‑коду&lt;/p&gt;
  &lt;p id=&quot;ZnHB&quot;&gt;&lt;strong&gt;Шаг 1: &lt;/strong&gt;Сканирование штрих-кода&lt;/p&gt;
  &lt;p id=&quot;dto5&quot;&gt;&lt;em&gt;Действие пользователя: &lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;5kN0&quot;&gt;- Пользователь находится на экране добавления продукта;&lt;/p&gt;
  &lt;p id=&quot;x8a0&quot;&gt;- Пользователь нажал кнопку «Сканировать штрих-код».&lt;/p&gt;
  &lt;p id=&quot;pO1b&quot;&gt;&lt;em&gt;Действие системы:&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;a4xI&quot;&gt;1. Система считывает штрих‑код и отправляет запрос:&lt;/p&gt;
  &lt;p id=&quot;myHM&quot;&gt;Request: POST /barcode/scan {code} на Backend.&lt;/p&gt;
  &lt;p id=&quot;O1hn&quot;&gt;Response: JSON&lt;/p&gt;
  &lt;p id=&quot;Ojvl&quot;&gt;- если данные получены, то перейти к шагу: отображение карточки продукта с БЖУ;&lt;/p&gt;
  &lt;p id=&quot;k1Wm&quot;&gt;- если данные не пришли, то перейти к шагу: ввод данных вручную.&lt;/p&gt;
  &lt;p id=&quot;Ttwh&quot;&gt;Используя такой подход аналитик делает свои доки читаемыми и однозначными, что помогает избежать лишних вопросов со стороны команды 🥂&lt;/p&gt;
  &lt;p id=&quot;oWKX&quot;&gt;➖➖➖&lt;/p&gt;
  &lt;p id=&quot;Ktwl&quot;&gt;&lt;strong&gt;Почему самообучение — не всегда выход? &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;rtyV&quot;&gt;Когда ты ищешь информацию в инете, то часто она уровня &amp;quot;обыватель&amp;quot;.&lt;/p&gt;
  &lt;p id=&quot;TXbh&quot;&gt;В итоге:&lt;/p&gt;
  &lt;p id=&quot;29TV&quot;&gt;✖️ неясно, &lt;strong&gt;что действительно нужно учить, а что — пустая трата времени&lt;/strong&gt;;&lt;/p&gt;
  &lt;p id=&quot;hcgG&quot;&gt;✖️ нет обратной связи — ты &lt;strong&gt;не понимаешь, правильно ли всё усвоил;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;pyY9&quot;&gt;&lt;strong&gt;✖️ &lt;/strong&gt;нет структуры и целостного понимания.&lt;/p&gt;
  &lt;p id=&quot;0nfk&quot;&gt;&lt;strong&gt;Что даёт мой курс? &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;hMXk&quot;&gt;✔️ &lt;strong&gt;БАЗУ&lt;/strong&gt;, которая нужна и для работы, и техсобесов,&lt;/p&gt;
  &lt;p id=&quot;JImV&quot;&gt;✔️ Много &lt;strong&gt;практики&lt;/strong&gt;,&lt;/p&gt;
  &lt;p id=&quot;ONAA&quot;&gt;✔️ Подробные комментарии к домашкам,&lt;/p&gt;
  &lt;p id=&quot;JOTp&quot;&gt;✔️ И главное — &lt;strong&gt;мой личный опыт и подходы&lt;/strong&gt;, которые превращают тебя не просто в аналитика, а в незаменимого специалиста, которого ценит команда&lt;/p&gt;
  &lt;p id=&quot;iIsW&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;YxVT&quot;&gt;ПОДПИСЫВАЙСЯ НА МОИ СОЦ СЕТИ:&lt;/h3&gt;
  &lt;p id=&quot;y7Gc&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://instagram.com/pro.analitica&quot; target=&quot;_blank&quot;&gt;ИНСТА &lt;/a&gt;| &lt;a href=&quot;https://t.me/proanalitica&quot; target=&quot;_blank&quot;&gt;ТЕЛЕГРАМ &lt;/a&gt;| &lt;a href=&quot;https://www.youtube.com/@proanalitika&quot; target=&quot;_blank&quot;&gt;YOUTUBE &lt;/a&gt;| &lt;a href=&quot;https://vk.com/proanalitica&quot; target=&quot;_blank&quot;&gt;VK&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</content></entry><entry><id>proanalitika:hUNapw3wQri</id><link rel="alternate" type="text/html" href="https://teletype.in/@proanalitika/hUNapw3wQri?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=proanalitika"></link><title>%D0%A2%D0%AB%20%D0%9A%D0%A0%D0%A3%D0%A2%D0%9E%D0%99%20%D0%90%D0%9D%D0%90%D0%9B%D0%98%D0%A2%D0%98%D0%9A</title><published>2025-05-21T07:35:25.685Z</published><updated>2025-05-21T07:38:05.782Z</updated><summary type="html">Как часто вы встречали такую крокозябру в текстах или в URL запросе?</summary><content type="html">
  &lt;p id=&quot;jnOn&quot;&gt;Как часто вы встречали такую крокозябру в текстах или в URL запросе?&lt;/p&gt;
  &lt;blockquote id=&quot;Msm8&quot;&gt;Курс только начался, а у ребят уже есть вопросы на эту тему и я хочу поделится ответом и с вами тоже.&lt;/blockquote&gt;
  &lt;p id=&quot;C3sh&quot;&gt;Кто-то думает, что это защита шифрование SSL, но нет это не так.&lt;/p&gt;
  &lt;p id=&quot;q8pe&quot;&gt;✔️ Это &lt;strong&gt;encoding&lt;/strong&gt; — это когда твоя строка превращается в безопасный формат для URL.&lt;/p&gt;
  &lt;p id=&quot;Byrp&quot;&gt;Любой браузер, может передать ограниченные символы и если мы хотим передать, например, кириллицу или кавычку, то чтобы сервер или браузер не свалились, нам понадобится их превратить в разрешенные.&lt;/p&gt;
  &lt;p id=&quot;XaTx&quot;&gt;Самый частый пример, где мы можем встретить encoding, это в поисковиках. Попробуйте вбить в Google слово матрешка и посмотрите в консоль разработчика.&lt;/p&gt;
  &lt;p id=&quot;1oFU&quot;&gt;Там вы увидите вместо нормального слова - это&lt;/p&gt;
  &lt;p id=&quot;isWI&quot;&gt;https://www.google.com/search?q=%D0%BC%D0%B0%D1%82%D1%80%D0%B5%D1%88%D0%BA%D0%B0&lt;/p&gt;
  &lt;p id=&quot;XhJv&quot;&gt;Еще, понимание, что это такое, может нам пригодится при разборе логов, потому что запрос прилетит именно в таком виде.&lt;/p&gt;
  &lt;p id=&quot;rlBV&quot;&gt;➖➖➖&lt;/p&gt;
  &lt;p id=&quot;Wxnk&quot;&gt;Но, как понять, что закодировано в сообщении, если мы не знаем изначальный запрос?&lt;/p&gt;
  &lt;p id=&quot;nswW&quot;&gt;✔️ Нам нужно сделать &lt;strong&gt;decoding&lt;/strong&gt; – обратное превращение закодированной строки в обычную.&lt;/p&gt;
  &lt;p id=&quot;uOus&quot;&gt;Обычно, если мы отправили запрос из браузера на сервер, то &lt;strong&gt;декодингом занимается сервер,&lt;/strong&gt; но если вдруг вам нужно понять, что в тексте, то &lt;strong&gt;вы можете сделать декодинг сами. &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;QX6t&quot;&gt;Самый сложный вариант - это найти &lt;strong&gt;таблицу UTF-8&lt;/strong&gt; и посмотреть, что значит конкретный символ.&lt;/p&gt;
  &lt;p id=&quot;jpMO&quot;&gt;Например, &lt;strong&gt;буква М будет выглядеть так %D0%BC&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;c8Ag&quot;&gt;Этим заниматься - это как-будто откатиться в прошлое и воспользоваться бумажным словарем для перевода английского слова вместо переводчика, поэтому лучше - &lt;strong&gt;воспользоваться спец сервисом по декодингу или нейронкой. &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;8EoR&quot;&gt;Сервисов много.&lt;/p&gt;
  &lt;p id=&quot;Iwqt&quot;&gt;💾 Например, &lt;strong&gt;https://www.urldecoder.org/ru&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;KMRc&quot;&gt;✔️ переходим по ссылке,&lt;/p&gt;
  &lt;p id=&quot;CCDY&quot;&gt;✔️ вбиваем наши кракозябры,&lt;/p&gt;
  &lt;p id=&quot;J5fy&quot;&gt;✔️ нажимаем декодировать&lt;/p&gt;
  &lt;p id=&quot;O9gM&quot;&gt;🪄 &lt;strong&gt;вуаля, у вас нормальная строка&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;vVyM&quot;&gt;Го декодировать заголовок  🥂&lt;/p&gt;
  &lt;p id=&quot;LkqN&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;Vso9&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;YxVT&quot;&gt;ПОДПИСЫВАЙСЯ НА МОИ СОЦ СЕТИ:&lt;/h3&gt;
  &lt;p id=&quot;y7Gc&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https://instagram.com/pro.analitica&quot; target=&quot;_blank&quot;&gt;ИНСТА &lt;/a&gt;| &lt;a href=&quot;https://t.me/proanalitica&quot; target=&quot;_blank&quot;&gt;ТЕЛЕГРАМ &lt;/a&gt;| &lt;a href=&quot;https://www.youtube.com/@proanalitika&quot; target=&quot;_blank&quot;&gt;YOUTUBE &lt;/a&gt;| &lt;a href=&quot;https://vk.com/proanalitica&quot; target=&quot;_blank&quot;&gt;VK&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</content></entry></feed>