Skip to content

Instantly share code, notes, and snippets.

@alexeiidonetskiy
Forked from imevro/readme.md
Created April 21, 2022 07:57
Show Gist options
  • Select an option

  • Save alexeiidonetskiy/1e52b6da4225500813f59ff0f4200ff1 to your computer and use it in GitHub Desktop.

Select an option

Save alexeiidonetskiy/1e52b6da4225500813f59ff0f4200ff1 to your computer and use it in GitHub Desktop.

Revisions

  1. @imevro imevro revised this gist Jan 23, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -86,6 +86,8 @@
    * вложенные поля через точку: `filter[location.settlementId]=134`
    * `filterNot` для обратного поведения (`filterNot[isDisabled]=true`: вернуть все объекты, где `isDisabled` не стоит в `true` — удобно, если `isDisabled` необязательное поле и может быть как и `null`, так и `false`)

    *📌 tip: такие фильтры реализовываются через Elastic и [Elasticsearch](https://www.elastic.co/products/elasticsearch)*


    ## Использовать версионирование
    Даже если это внутренний API — меньше когнитивная нагрузка на «сломали ли АПИ или будет работать?». Раз стоит версия, значит разработчик пообещал что она будет стабильна.
  2. @imevro imevro revised this gist Jan 23, 2019. 1 changed file with 6 additions and 1 deletion.
    7 changes: 6 additions & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -15,6 +15,7 @@
    - [Использовать JSON и обязательно через хедер `accept: application/json`](#-------------json----------------------------accept--application-json-)
    - [Давать чёткие ошибки](#--------------------)
    - [Не использовать общий нейминг](#-----------------------------)
    - [Документировать](#---------------)


    Основное, на что нужно обратить внимание:
    @@ -106,4 +107,8 @@
    ## Не использовать общий нейминг
    Типа `items`, `products`, `elements`.

    Если возвращаете список автомобилей — ресурс `/cars`, если производителей — `/manufacturers`, мест — `/places`.
    Если возвращаете список автомобилей — ресурс `/cars`, если производителей — `/manufacturers`, мест — `/places`.


    ## Документировать
    Желательно через [Сваггер](https://swagger.io/)
  3. @imevro imevro revised this gist Jan 23, 2019. No changes.
  4. @imevro imevro revised this gist Jan 23, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@

    - [Держать простым](#---------------)
    - [Не забывать про методы](#----------------------)
    - [Использовать корректные [статус-коды](https://httpstatuses.com/) в ответах](#--------------------------------------https---httpstatusescom------------)
    - [Использовать корректные статус-коды в ответах](#--------------------------------------https---httpstatusescom------------)
    - [Ресурсы как существительное, не глагол](#--------------------------------------)
    - [Использовать множественное значение](#-----------------------------------)
    - [Использовать пагинацию, а не выдавать всё разом](#-----------------------------------------------)
  5. @imevro imevro revised this gist Jan 23, 2019. 1 changed file with 17 additions and 0 deletions.
    17 changes: 17 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,22 @@
    *Based on [RESTful API Design — Step By Step Guide](https://hackernoon.com/restful-api-design-step-by-step-guide-2f2c9f9fcdbf)*

    - [Держать простым](#---------------)
    - [Не забывать про методы](#----------------------)
    - [Использовать корректные [статус-коды](https://httpstatuses.com/) в ответах](#--------------------------------------https---httpstatusescom------------)
    - [Ресурсы как существительное, не глагол](#--------------------------------------)
    - [Использовать множественное значение](#-----------------------------------)
    - [Использовать пагинацию, а не выдавать всё разом](#-----------------------------------------------)
    - [В коллекциях возвращать информацию о пагинации](#----------------------------------------------)
    - [Использовать квери-параметры для GET запросов, если нужно сузить выборку](#---------------------------------get------------------------------------)
    + [Пагинация](#---------)
    + [Сортировка](#----------)
    + [Фильтры](#-------)
    - [Использовать версионирование](#----------------------------)
    - [Использовать JSON и обязательно через хедер `accept: application/json`](#-------------json----------------------------accept--application-json-)
    - [Давать чёткие ошибки](#--------------------)
    - [Не использовать общий нейминг](#-----------------------------)


    Основное, на что нужно обратить внимание:

    ## Держать простым
  6. @imevro imevro created this gist Jan 23, 2019.
    92 changes: 92 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,92 @@
    *Based on [RESTful API Design — Step By Step Guide](https://hackernoon.com/restful-api-design-step-by-step-guide-2f2c9f9fcdbf)*

    Основное, на что нужно обратить внимание:

    ## Держать простым
    ![](https://i.imgur.com/LN9UEbd.png)


    ## Не забывать про методы
    * `GET` запрашивает данные
    * `POST` отправляет чтобы создать
    * `PUT` отправляет чтобы обновить
    * `DELETE` удаляет
    ![](https://i.imgur.com/umuV0iQ.png)


    ## Использовать корректные [статус-коды](https://httpstatuses.com/) в ответах
    Будет проще отрабатывать ответ и меньше работы: вместо ошибки `{ error: 'Сервер упал, к сожалению' }` достаточно послать код [503](https://httpstatuses.com/503)
    ![](https://i.imgur.com/9FdtWIE.png)


    ## Ресурсы как существительное, не глагол
    У нас же есть методы!
    ![](https://i.imgur.com/N2Fpdmh.png)


    ## Использовать множественное значение
    И принцип от общего к частному: сначала продукты, потом — конкретный продукт.
    ![](https://i.imgur.com/qgkYrEL.png)


    ## Использовать пагинацию, а не выдавать всё разом
    Самая удобная пагинация — на оффсетах (когда через квери-параметры передаётся `offset` и `limit`)
    ![](https://i.imgur.com/Y5dGdYg.png)


    ## В коллекциях возвращать информацию о пагинации
    В коллекциях удобно иметь структуру
    ```js
    {
    items: Array<{MyModel}>,
    pagination: {
    offset: Number = 0,
    limit: Number = 32,
    total: Number,
    }
    }
    ```


    ## Использовать квери-параметры для GET запросов, если нужно сузить выборку
    *[Примеры квери-параметров](https://medium.com/@fullsour/a346790e8a6d)*

    По моему субъективному опыту в несколько лет, самый удобный формат таков:

    #### Пагинация
    Через `limit=&offset=&`

    #### Сортировка
    Через `orderBy[key]={asc,desc}` (`orderBy[name]=asc` или `orderBy[id]=desc`)

    #### Фильтры
    * фильтры через префикс `filter[]` и ключ (например, `filter[id]`, `filter[name]`, `filter[price]`)
    * по строке через `*`: `filter[name]=*esl*` для поиска T**esl**a
    * несколько значений через `,`: `filter[id]=1,2,3,4`
    * диапазон через `..`, где оба поля опциональны: `filter[price]=..100` (до 100), `filter[price]=200..` (от 200), `filter[price]=50..500` (от 50 до 500)
    * булеан-значения в прямом виде: `filter[isResale]=true`
    * вложенные поля через точку: `filter[location.settlementId]=134`
    * `filterNot` для обратного поведения (`filterNot[isDisabled]=true`: вернуть все объекты, где `isDisabled` не стоит в `true` — удобно, если `isDisabled` необязательное поле и может быть как и `null`, так и `false`)


    ## Использовать версионирование
    Даже если это внутренний API — меньше когнитивная нагрузка на «сломали ли АПИ или будет работать?». Раз стоит версия, значит разработчик пообещал что она будет стабильна.
    ![](https://i.imgur.com/0sPy55Q.png)


    ## Использовать JSON и обязательно через хедер `accept: application/json`
    АПИ должен явно задавать через хедер `accept` что он принимает mime-type `application/json` и никакой больше.
    *📌 Исключение: файлы всё ещё удобнее заливать через `multipart/form-data` — тут велосипедов строить не нужно*

    Клиент должен передавать заголовок `content-type` с тем mime-type, который он хочет послать. Сервер явно должен обрабатывать этот хедер и слать ошибку, если он не принимает этот `content-type`.


    ## Давать чёткие ошибки
    Ошибки дают понимание конкретной проблемы
    ![](https://i.imgur.com/kVMWfi7.png)


    ## Не использовать общий нейминг
    Типа `items`, `products`, `elements`.

    Если возвращаете список автомобилей — ресурс `/cars`, если производителей — `/manufacturers`, мест — `/places`.