From 4fcc0a228b0cbf9798fdf7800c0490a7d8025aac Mon Sep 17 00:00:00 2001 From: Sergey Konstantinov Date: Sun, 2 Jul 2023 15:44:46 +0300 Subject: [PATCH] HTTP Section finished --- .../08.md | 42 +++++++++++++++++- .../08.md | 43 ++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/en/clean-copy/05-[Work in Progress] Section IV. HTTP APIs & REST Architectural Principles/08.md b/src/en/clean-copy/05-[Work in Progress] Section IV. HTTP APIs & REST Architectural Principles/08.md index a54a9e8..d2dc9c4 100644 --- a/src/en/clean-copy/05-[Work in Progress] Section IV. HTTP APIs & REST Architectural Principles/08.md +++ b/src/en/clean-copy/05-[Work in Progress] Section IV. HTTP APIs & REST Architectural Principles/08.md @@ -1 +1,41 @@ -### Final Provisions and General Recommendations \ No newline at end of file +### [Final Provisions and General Recommendations][http-api-final-recommendations] + +Let's summarize what was discussed in the previous chapters. To design a fine HTTP API one needs to: + 1. Describe a happy path, i.e. draw a diagram of all HTTP calls that occur during a normal work cycle of an application. + 2. Interpret every call as an operation executed on a resource and assemble a nomenclature of URLs and applicable methods accordingly. + 3. Enumerate errors that might occur during operation execution and determine paths to restore the application state for clients after receiving an error. + 4. Decide which functionality will be communicated at the HTTP protocol level, i.e., which standard protocol capabilities to use in conjunction with what tools and software and the extent of their usage. + 5. Develop a detailed specification regarding the aforementioned list points. + 6. Check yourselves: elaborate on paragraphs 1-3 to write pseudo-code for the application's business logic in accordance with the specification, and evaluate the convenience, understandability and readability of your API. + +Additionally, we'd like to provide some code style advice: + + 1. Do not differentiate paths with trailing `/` and without it. Employ a default policy (we would rather recommend ending paths with `/` for a simple reason: it allows for referring to operations on the domain root resource in a readable manner as `VERB /`). If you decide to prohibit one of the variants (let's say, all URLs must end with a trailing slash), make a redirect or provide a very readable error message if a developer tries to call a URL formatted otherwise. + + 2. Include common headers (such as `Date`, `Content-Type`, `Content-Encoding`, `Content-Length`, `Cache-Control`, `Retry-After`, etc.) in the responses and generally avoid relying on clients to guess default protocol parameters correctly. + + 3. Support the `OPTIONS` method and the [CORS protocol](https://fetch.spec.whatwg.org/#cors-protocol) just in case your API needs to be accessed from a Web browser. + + 4. Choose a casing rule and a rule for transforming casing while moving a parameter from one part of an HTTP request to another. + + 5. Always leave an opportunity for backward-compatible extension of an API method. In particular, always return a JSON object as the endpoint response root as objects can always be extended with a new field, unlike arrays and primitives. + * Let us also note that an empty string is invalid JSON, so you need to return an empty object `{}` in `200` responses even if it doesn't have a specific meaning. Alternatively, you can use the `204 No Content` status code with an empty body, which is not extensible. + + 6. For every `GET` response, provide explicit caching parameters (otherwise, there is always a chance that a client or an intermediate agent invents them on their own). + + 7. Do not employ known possibilities to serve requests in violation of the standard and avoid exploiting “gray zones” of the protocol. In particular: + * Do not place unsafe operations behind the `GET` verb, and do not place non-idempotent operations behind the `PUT` / `DELETE` methods. + * Maintain the `GET` / `PUT` / `DELETE` operations symmetry. + * Do not allow `GET` / `HEAD` / `DELETE` requests to have a body and do not provide bodies in response to `HEAD` requests or alongside the `204` status code. + * Do not invent your own standards for passing arrays and nested objects as query parameters. It is better to use an HTTP verb that allows having a body, or as a last resort pass the parameter as a base64-encoded JSON-stringified value. + * Do not put parameters that require escaping (i.e., non-alphanumeric ones) in a path or a domain of a URL. Use query or body parameters for this purpose. + + 8. Familiarize yourself with at least the basics of typical vulnerabilities in HTTP APIs used by attackers, such as: + * [CSRF](https://owasp.org/www-community/attacks/csrf) + * [SSRF](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) + * [HTTP Response Splitting](https://owasp.org/www-community/attacks/HTTP_Response_Splitting) + * [Unvalidated Redirects and Forwards](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) + + and include protection against these attack vectors at the webserver software level. The OWASP community provides a [good cheatsheet on the best HTTP API security practices](https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html). + +In conclusion, we would like to make the following statement: building an HTTP API is relying on the common knowledge of HTTP call semantics and drawing benefits from it by leveraging various software built upon this paradigm, from client frameworks to server gateways, and developers reading and understanding API specifications. In this sense, the HTTP ecosystem provides probably the most comprehensive vocabulary, both in terms of profoundness and adoption, compared to other technologies, allowing for describing many different situations that may arise in client-server communication. While the technology is not perfect and has its flaws, for a *public API* vendor, it is the default choice, and opting for other technologies rather needs to be substantiated as of today. \ No newline at end of file diff --git a/src/ru/clean-copy/05-[В разработке] Раздел IV. HTTP API и REST/08.md b/src/ru/clean-copy/05-[В разработке] Раздел IV. HTTP API и REST/08.md index 8543acc..93246cd 100644 --- a/src/ru/clean-copy/05-[В разработке] Раздел IV. HTTP API и REST/08.md +++ b/src/ru/clean-copy/05-[В разработке] Раздел IV. HTTP API и REST/08.md @@ -1 +1,42 @@ -### Заключительные положения и общие рекомендации \ No newline at end of file +### [Заключительные положения и общие рекомендации][http-api-final-recommendations] + +Подведём итог описанному в предыдущих главах. Чтобы разработать качественный HTTP API, необходимо: + 1. Описать happy path, т.е. составить диаграмму вызовов для стандартного цикла работы клиентского приложения. + 2. Определить каждый вызов как операцию над некоторым ресурсом и, таким образом, составить номенклатуру URL и применимых методов. + 3. Понять, какие ошибки возможны при выполнении операций и каким образом клиент должен восстанавливаться из какого состояния. + 4. Решить, какая функциональность будет передана на уровень протокола HTTP [какие стандартные возможности протокола будут использованы в сопряжении с какими инструментами разработки] и в каком объёме. + 5. Опираясь на решения 1-4, разработать конкретную спецификацию. + 6. Проверить себя: пройти по пунктам 1-3, написать псевдокод бизнес-логики приложения согласно разработанной спецификации, и оценить, насколько удобным, понятным и читабельным оказался результирующий API. + +Позволим себе так же дать несколько советов по code style: + + 1. Не различайте пути с `/` на конце и без него и примите какую-то рекомендацию по умолчанию (мы рекомендуем все пути заканчивать на `/` — по простой причине, это позволяет разумно описать обращение к корню домена как `ГЛАГОЛ /`). Если вы решили запретить один из вариантов (скажем, пути без слэша в конце), при обращении по второму варианту должен быть или редирект или однозначно читаемая ошибка. + + 2. Включайте в ответы стандартные заголовки — `Date`, `Content-Type`, `Content-Encoding`, `Content-Length`, `Cache-Control`, `Retry-After` — и вообще старайтесь не полагаться на то, что клиент правильно догадывается о параметрах протокола по умолчанию. + + 3. Поддержите метод `OPTIONS` и [протокол CORS](https://fetch.spec.whatwg.org/#cors-protocol) на случай, если ваш API захотят использовать из браузеров. + + 4. Определитесь с правилами выбора кейсинга параметров (и преобразований кейсинга при перемещении параметра между различными частями запроса) и придерживайтесь их. + + 5. Всегда оставляйте себе возможность обратно-совместимого расширения операции API. В частности, всегда возвращайте корневой JSON-объект в ответах эндпойтов — потому что приписать новые поля к объекту вы можете, а к массивам и примитивам — нет. + * Отметим также, что пустая строка не является валидным JSON, поэтому корректнее возвращать пустой объект `{}` там, где ответа не подразумевается (или статус `204 No Content` с пустым телом, но тогда эндпойнт нельзя будет расширить в будущем). + + 6. Для всех `GET`-запросов указывайте политику кэширования (иначе всегда есть шанс, что клиент или промежуточный агент придумает её за вас). + + 7. Не эксплуатируйте известные возможности оперировать запросами в нарушение стандарта и не изобретайте свои решения для «серых зон» протокола. В частности: + * не размещайте модифицирующие операции за методом `GET` и неидемпотентные операции за `PUT` / `DELETE`; + * соблюдайте симметрию `GET` / `PUT` / `DELETE` методов; + * не позволяйте `GET` / `HEAD` / `DELETE`-запросам иметь тело, не возвращайте тело в ответе метода `HEAD` или совместно со статус-кодом `204 No Content`; + * не придумывайте свой стандарт для передачи массивов и вложенных объектов в query — лучше воспользоваться HTTP-глаголом, позволяющим запросу иметь тело, или, в крайнем случае, передать параметры в виде base64-кодированного JSON-поля; + * не размещайте в пути и домене URL параметры, по формату требующие эскейпинга (т.е. могущие содержать символы, отличные от цифр и букв латинского алфавита); для этой цели лучше воспользоваться query-параметрами или телом запроса. + + 8. Ознакомьтесь хотя бы с основными видами уязвимостей в типичных имплементациях HTTP API, которыми могут воспользоваться злоумышленники: + * [CSFR](https://owasp.org/www-community/attacks/csrf) + * [SSRF](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) + * [HTTP Response Splitting](https://owasp.org/www-community/attacks/HTTP_Response_Splitting) + * [Unvalidated Redirects and Forwards](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) + + и заложите защиту от этих векторов атак на уровне вашего серверного ПО. Организация OWASP предоставляет [хороший обзор лучших security-практик для HTTP API](https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html). + + +В заключение хотелось бы сказать следующее: HTTP API — это способ организовать ваше API так, чтобы полагаться на понимание семантики операций как разнообразным программным обеспечением, от клиентских фреймворков до серверных гейтвеев, так и разработчиком, который читает спецификацию. В этом смысле экосистема HTTP предоставляет пожалуй что наиболее широкий (и в плане глубины, и в плане распространённости) по сравнению с другими технологиями словарь для описания самых разнообразных ситуаций, возникающих во время работы клиент-серверных приложений. Разумеется, эта технология не лишена своих недостатков, но для разработчика *публичного* API она является выбором по умолчанию — на сегодняшний день скорее надо обосновывать отказ от HTTP API чем выбор в его пользу. \ No newline at end of file