1
0
mirror of https://github.com/twirl/The-API-Book.git synced 2025-01-23 17:53:04 +02:00

small build fixes + fresh build

This commit is contained in:
Sergey Konstantinov 2022-07-10 23:34:14 +03:00
parent 33ca3d2750
commit 2754a52530
9 changed files with 22 additions and 10 deletions

Binary file not shown.

View File

@ -130,12 +130,14 @@ code {
}
pre {
margin: 1em 0;
margin: 1em auto;
padding: 1em;
border-radius: 0.25em;
border-top: 1px solid rgba(0, 0, 0, 0.45);
border-left: 1px solid rgba(0, 0, 0, 0.45);
box-shadow: 0.1em 0.1em 0.1em rgba(0, 0, 0, 0.45);
width: 90%;
box-sizing: border-box;
page-break-inside: avoid;
overflow-x: auto;
font-size: 90%;
@ -1939,7 +1941,10 @@ POST /v1/orders
<p>With the API popularity growth, it will inevitably become necessary to introduce technical means of preventing illicit API usage, such as displaying captcha, setting honeypots, raising the ‘too many requests’ exceptions, installing anti-DDoS proxies, etc. All these things cannot be done if the corresponding errors and messages were not described in the docs from the very beginning.</p>
<p>You are not obliged to actually generate those exceptions, but you might stipulate this possibility in the terms of service. For example, you might describe the <code>429 Too Many Requests</code> error or captcha redirect, but implement the functionality when it's actually needed.</p>
<p>It is extremely important to leave a room for multi-factored authentication (such as TOTP, SMS, or 3D-secure-like technologies) in case it's possible to make payments through the API. In this case, it's a must have from the very beginning.</p>
<h5><a href="#chapter-11-paragraph-20" id="chapter-11-paragraph-20" class="anchor">20. No results is a result</a></h5>
<h5><a href="#chapter-11-paragraph-20" id="chapter-11-paragraph-20" class="anchor">20. Don't provide endpoints for mass downloading of sensitive data</a></h5>
<p>If it's possible to get through the API users' personal data, bank card numbers, private messages, or any other kind of information, exposing of which might seriously harm users, partners, and/or you — there must be <em>no</em> methods of bulk getting the data, or at least there must be rate limiters, page size restrictions, and, ideally, multi-factored authentication in front of them.</p>
<p>Often, making such offloads on an ad-hoc basis, e.g. in bypass of the API, is a reasonable practice.</p>
<h5><a href="#chapter-11-paragraph-21" id="chapter-11-paragraph-21" class="anchor">21. No results is a result</a></h5>
<p>If a server processed a request correctly and no exceptional situation occurred — there must be no error. Regretfully, an antipattern is widespread — of throwing errors when zero results are found.</p>
<p><strong>Bad</strong></p>
<pre><code>POST /search
@ -1966,7 +1971,7 @@ POST /v1/orders
}
</code></pre>
<p>This rule might be reduced to: if an array is the result of the operation, then the emptiness of that array is not a mistake, but a correct response. (Of course, if an empty array is acceptable semantically; an empty array of coordinates is a mistake for sure.)</p>
<h5><a href="#chapter-11-paragraph-21" id="chapter-11-paragraph-21" class="anchor">21. Localization and internationalization</a></h5>
<h5><a href="#chapter-11-paragraph-22" id="chapter-11-paragraph-22" class="anchor">22. Localization and internationalization</a></h5>
<p>All endpoints must accept language parameters (for example, in a form of the <code>Accept-Language</code> header), even if they are not being used currently.</p>
<p>It is important to understand that the user's language and the user's jurisdiction are different things. Your API working cycle must always store the user's location. It might be stated either explicitly (requests contain geographical coordinates) or implicitly (initial location-bound request initiates session creation which stores the location), but no correct localization is possible in absence of location data. In most cases reducing the location to just a country code is enough.</p>
<p>The thing is that lots of parameters potentially affecting data formats depend not on language, but on a user's location. To name a few: number formatting (integer and fractional part delimiter, digit groups delimiter), date formatting, the first day of the week, keyboard layout, measurement units system (which might be non-decimal!), etc. In some situations, you need to store two locations: user residence location and user ‘viewport’. For example, if a US citizen is planning a European trip, it's convenient to show prices in local currency, but measure distances in miles and feet.</p>

Binary file not shown.

Binary file not shown.

View File

@ -130,12 +130,14 @@ code {
}
pre {
margin: 1em 0;
margin: 1em auto;
padding: 1em;
border-radius: 0.25em;
border-top: 1px solid rgba(0, 0, 0, 0.45);
border-left: 1px solid rgba(0, 0, 0, 0.45);
box-shadow: 0.1em 0.1em 0.1em rgba(0, 0, 0, 0.45);
width: 90%;
box-sizing: border-box;
page-break-inside: avoid;
overflow-x: auto;
font-size: 90%;
@ -1940,9 +1942,12 @@ POST /v1/orders
<p>Легко заметить, что в этом примере нет способа разрешить ошибку в один шаг — эту ситуацию требуется предусмотреть отдельно, и либо изменить параметры расчёта (минимальная сумма заказа не учитывает скидки), либо ввести специальную ошибку для такого кейса.</p>
<h5><a href="#chapter-11-paragraph-19" id="chapter-11-paragraph-19" class="anchor">19. Предусмотрите ограничения</a></h5>
<p>С ростом популярности API вам неизбежно придётся внедрять технические средства защиты от недобросовестного использования — такие, как показ капчи, расстановка приманок-honeypot-ов, возврат ошибок вида «слишком много запросов», постановка прокси-защиты от DDoS перед эндпойнтами и так далее. Всё это невозможно сделать, если вы не предусмотрели такой возможности изначально, а именно — не ввели соответствующей номенклатуры ошибок и предупреждений.</p>
<p>Вы не обязаны с самого начала такие ошибки действительно генерировать — но вы можете предусмотреть их на будущее. Например, вы можете описать ошибку <code>429 Too Many Requests</code> или редирект на показ капчи, но не имплементировать возврат таких ответов, пока не возникнет такая необходимость.</p>
<p>Вы не обязаны с самого начала такие ошибки действительно генерировать — но вы можете предусмотреть их на будущее. Например, вы можете описать ошибку <code>429 Too Many Requests</code> или перенаправление на показ капчи, но не имплементировать возврат таких ответов, пока не возникнет такая необходимость.</p>
<p>Отдельно необходимо уточнить, что в тех случаях, когда через API можно совершать платежи, ввод дополнительных факторов аутентификации пользователя (через TOTP, SMS или технологии типа 3D-Secure) должен быть предусмотрен обязательно.</p>
<h5><a href="#chapter-11-paragraph-20" id="chapter-11-paragraph-20" class="anchor">20. Отсутствие результата — тоже результат</a></h5>
<h5><a href="#chapter-11-paragraph-20" id="chapter-11-paragraph-20" class="anchor">20. Не предоставляйте endpoint-ов массового получения чувствительных данных</a></h5>
<p>Если через API возможно получение персональных данных, номер банковских карт, переписки пользователей и прочей информации, раскрытие которой нанесёт большой ущерб пользователям, партнёрам и/или вам — методов массового получения таких данных в API быть не должно, или, по крайней мере, на них должны быть ограничения на частоту запросов, размер страницы данных, а в идеале ещё и многофакторная аутентификация.</p>
<p>Часто разумной практикой является предоставление таких массовых выгрузок по запросу, т.е. фактически в обход API.</p>
<h5><a href="#chapter-11-paragraph-21" id="chapter-11-paragraph-21" class="anchor">21. Отсутствие результата — тоже результат</a></h5>
<p>Если сервер корректно обработал вопрос и никакой внештатной ситуации не возникло — следовательно, это не ошибка. К сожалению, весьма распространён антипаттерн, когда отсутствие результата считается ошибкой.</p>
<p><strong>Плохо</strong></p>
<pre><code>POST /search
@ -1969,7 +1974,7 @@ POST /v1/orders
}
</code></pre>
<p>Это правило вообще можно упростить до следующего: если результатом операции является массив данных, то пустота этого массива — не ошибка, а штатный ответ. (Если, конечно, он допустим по смыслу; пустой массив координат, например, является ошибкой.)</p>
<h5><a href="#chapter-11-paragraph-21" id="chapter-11-paragraph-21" class="anchor">21. Локализация и интернационализация</a></h5>
<h5><a href="#chapter-11-paragraph-22" id="chapter-11-paragraph-22" class="anchor">22. Локализация и интернационализация</a></h5>
<p>Все эндпойнты должны принимать на вход языковые параметры (например, в виде заголовка <code>Accept-Language</code>), даже если на текущем этапе нужды в локализации нет.</p>
<p>Важно понимать, что язык пользователя и юрисдикция, в которой пользователь находится — разные вещи. Цикл работы вашего API всегда должен хранить локацию пользователя. Либо она задаётся явно (в запросе указываются географические координаты), либо неявно (первый запрос с географическими координатами инициировал создание сессии, в которой сохранена локация) — но без локации корректная локализация невозможна. В большинстве случаев локацию допустимо редуцировать до кода страны.</p>
<p>Дело в том, что множество параметров, потенциально влияющих на работу API, зависят не от языка, а именно от расположения пользователя. В частности, правила форматирования чисел (разделители целой и дробной частей, разделители разрядов) и дат, первый день недели, раскладка клавиатуры, система единиц измерения (которая к тому же может оказаться не десятичной!) и так далее. В некоторых ситуациях необходимо хранить две локации: та, в которой пользователь находится, и та, которую пользователь сейчас просматривает. Например, если пользователь из США планирует туристическую поездку в Европу, то цены ему желательно показывать в местной валюте, но отформатированными согласно правилам американского письма.</p>

Binary file not shown.

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/jpg" href="assets/favicon.jpg" />
<link rel="icon" type="image/png" href="assets/favicon.png" />
<title>
Sergey Konstantinov. The API
</title>

View File

@ -4,7 +4,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/jpg" href="assets/favicon.jpg" />
<link rel="icon" type="image/png" href="assets/favicon.png" />
<title>
Сергей Константинов. API
</title>

View File

@ -117,12 +117,14 @@ code {
}
pre {
margin: 1em 0;
margin: 1em auto;
padding: 1em;
border-radius: 0.25em;
border-top: 1px solid rgba(0, 0, 0, 0.45);
border-left: 1px solid rgba(0, 0, 0, 0.45);
box-shadow: 0.1em 0.1em 0.1em rgba(0, 0, 0, 0.45);
width: 90%;
box-sizing: border-box;
page-break-inside: avoid;
overflow-x: auto;
font-size: 90%;