[{"data":1,"prerenderedAt":516},["ShallowReactive",2],{"content-\u002F05-web\u002F03-rest-api":3},{"id":4,"title":5,"body":6,"description":17,"difficulty":500,"extension":501,"meta":502,"module":503,"navigation":504,"next":505,"order":489,"path":506,"prev":507,"seo":508,"slug":509,"stem":510,"tags":511,"__hash__":515},"content\u002F05-web\u002F03-rest-api\u002Findex.md","REST API",{"type":7,"value":8,"toc":482},"minimark",[9,14,18,21,26,33,36,47,50,56,63,65,69,79,82,87,90,96,100,103,109,112,116,119,125,131,137,143,154,163,167,170,172,176,179,264,274,278,281,287,298,300,304,310,313,315,319,322,328,334,340,342,346,349,355,361,367,370,372,376,385,393,401,421,437,452,474],[10,11,13],"h1",{"id":12},"что-такое-api-rest-и-restful","Что такое API, REST и RESTful",[15,16,17],"p",{},"Эти три термина звучат на каждом собеседовании и в каждом описании вакансии. При этом многие разработчики используют их как синонимы, хотя это разные вещи. Разберём каждый по порядку.",[19,20],"hr",{},[22,23,25],"h2",{"id":24},"что-такое-api","Что такое API",[15,27,28,32],{},[29,30,31],"strong",{},"API"," (Application Programming Interface) — это интерфейс, через который одна программа общается с другой. Ключевое слово — интерфейс: набор правил и контрактов о том, как именно происходит общение.",[15,34,35],{},"Простая аналогия: вы приходите в ресторан. Вы не идёте на кухню и не говорите повару что готовить — вы общаетесь с официантом. Официант принимает заказ, передаёт на кухню, приносит результат. Вам не нужно знать как устроена кухня. Официант и есть API.",[37,38,43],"pre",{"className":39,"code":41,"language":42},[40],"language-text","Вы (клиент)  →  Официант (API)  →  Кухня (сервер\u002Fбаза данных)\n     ↑                                        │\n     └────────────────────────────────────────┘\n                    Готовое блюдо (ответ)\n","text",[44,45,41],"code",{"__ignoreMap":46},"",[15,48,49],{},"В мире программирования то же самое:",[37,51,54],{"className":52,"code":53,"language":42},[40],"Браузер\u002FПриложение  →  API  →  Сервер + База данных\n        ↑                               │\n        └───────────────────────────────┘\n                   JSON-ответ\n",[44,55,53],{"__ignoreMap":46},[15,57,58,59,62],{},"API бывают разные — не только веб. Операционная система предоставляет API для работы с файлами. Библиотека предоставляет API в виде функций. Но когда говорят \"сделать API\" в контексте backend — обычно имеют в виду ",[29,60,61],{},"веб-API",": интерфейс доступный через HTTP.",[19,64],{},[22,66,68],{"id":67},"что-такое-rest","Что такое REST",[15,70,71,74,75,78],{},[29,72,73],{},"REST"," (Representational State Transfer) — это не технология и не протокол. Это ",[29,76,77],{},"архитектурный стиль",": набор принципов того, как должен быть устроен веб-API.",[15,80,81],{},"Придумал REST Рой Филдинг в 2000 году в своей диссертации. Он описал 6 принципов, которым должна следовать система чтобы называться REST. На практике важны четыре из них.",[83,84,86],"h3",{"id":85},"принцип-1-клиент-сервер","Принцип 1: Клиент-сервер",[15,88,89],{},"Клиент и сервер разделены и развиваются независимо. Фронтенд не знает как устроена база данных. Бэкенд не знает как выглядит интерфейс. Они общаются только через API.",[37,91,94],{"className":92,"code":93,"language":42},[40],"Мобильное приложение ─┐\n                       ├──► API ──► База данных\nВеб-браузер ──────────┘\n\nТри разных клиента, один API — каждый развивается независимо\n",[44,95,93],{"__ignoreMap":46},[83,97,99],{"id":98},"принцип-2-stateless-без-состояния","Принцип 2: Stateless — без состояния",[15,101,102],{},"Каждый запрос самодостаточен. Сервер не помнит предыдущих запросов. Вся информация необходимая для обработки запроса содержится в самом запросе:",[37,104,107],{"className":105,"code":106,"language":42},[40],"\u002F\u002F Плохо — сервер помнит \"текущего пользователя\"\nGET \u002Fcurrent-user\u002Ftodos      ← кто текущий пользователь? сервер \"помнит\"\n\n\u002F\u002F Хорошо — всё необходимое в запросе\nGET \u002Fusers\u002F42\u002Ftodos\nAuthorization: Bearer eyJ...  ← идентификация в каждом запросе\n",[44,108,106],{"__ignoreMap":46},[15,110,111],{},"Stateless делает сервер масштабируемым: любой инстанс может обработать любой запрос, потому что не нужно разделять состояние между серверами.",[83,113,115],{"id":114},"принцип-3-единый-интерфейс","Принцип 3: Единый интерфейс",[15,117,118],{},"Это главный принцип REST. Он состоит из нескольких правил:",[15,120,121,124],{},[29,122,123],{},"Ресурсы идентифицируются через URL."," В REST всё — это ресурс. Пользователь, задача, заказ — ресурс. URL — это адрес ресурса:",[37,126,129],{"className":127,"code":128,"language":42},[40],"\u002Fusers          — коллекция пользователей\n\u002Fusers\u002F42       — конкретный пользователь\n\u002Fusers\u002F42\u002Ftodos — задачи конкретного пользователя\n",[44,130,128],{"__ignoreMap":46},[15,132,133,136],{},[29,134,135],{},"Действия определяются HTTP-методами",", а не URL:",[37,138,141],{"className":139,"code":140,"language":42},[40],"GET    \u002Ftodos      — получить список\nPOST   \u002Ftodos      — создать новую\nGET    \u002Ftodos\u002F1    — получить одну\nPUT    \u002Ftodos\u002F1    — обновить полностью\nPATCH  \u002Ftodos\u002F1    — обновить частично\nDELETE \u002Ftodos\u002F1    — удалить\n",[44,142,140],{"__ignoreMap":46},[15,144,145,146,149,150,153],{},"URL отвечает на вопрос ",[29,147,148],{},"\"что\"",", метод — на вопрос ",[29,151,152],{},"\"что сделать\"",".",[15,155,156,159,160,153],{},[29,157,158],{},"Представление ресурса отделено от самого ресурса."," Один и тот же ресурс может быть представлен по-разному — JSON, XML, HTML — в зависимости от того что запрашивает клиент через заголовок ",[44,161,162],{},"Accept",[83,164,166],{"id":165},"принцип-4-кешируемость","Принцип 4: Кешируемость",[15,168,169],{},"Ответы должны явно указывать можно ли их кешировать. GET-запросы как правило кешируются, POST\u002FPUT\u002FDELETE — нет. Это позволяет CDN и браузерам не делать лишние запросы к серверу.",[19,171],{},[22,173,175],{"id":174},"http-методы-и-статус-коды-в-контексте-rest","HTTP-методы и статус коды в контексте REST",[15,177,178],{},"REST использует HTTP как протокол, и семантика методов важна:",[180,181,182,198],"table",{},[183,184,185],"thead",{},[186,187,188,192,195],"tr",{},[189,190,191],"th",{},"Метод",[189,193,194],{},"Действие",[189,196,197],{},"Идемпотентен?",[199,200,201,215,228,240,252],"tbody",{},[186,202,203,209,212],{},[204,205,206],"td",{},[44,207,208],{},"GET",[204,210,211],{},"Получить ресурс",[204,213,214],{},"Да",[186,216,217,222,225],{},[204,218,219],{},[44,220,221],{},"POST",[204,223,224],{},"Создать ресурс",[204,226,227],{},"Нет",[186,229,230,235,238],{},[204,231,232],{},[44,233,234],{},"PUT",[204,236,237],{},"Заменить ресурс целиком",[204,239,214],{},[186,241,242,247,250],{},[204,243,244],{},[44,245,246],{},"PATCH",[204,248,249],{},"Обновить частично",[204,251,227],{},[186,253,254,259,262],{},[204,255,256],{},[44,257,258],{},"DELETE",[204,260,261],{},"Удалить ресурс",[204,263,214],{},[15,265,266,269,270,273],{},[29,267,268],{},"Идемпотентность"," — если выполнить запрос несколько раз, результат тот же что и от одного. ",[44,271,272],{},"DELETE \u002Ftodos\u002F1"," можно вызвать трижды — после первого раза задача удалена, следующие вызовы ничего не меняют (возвращают 404, но состояние системы не меняется).",[83,275,277],{"id":276},"статус-коды","Статус коды",[15,279,280],{},"Статус код — часть контракта REST. Клиент должен понимать что произошло без чтения тела ответа:",[37,282,285],{"className":283,"code":284,"language":42},[40],"2xx — успех\n  200 OK           — запрос выполнен\n  201 Created      — ресурс создан (ответ на POST)\n  204 No Content   — успех, тело пустое (ответ на DELETE)\n\n4xx — ошибка клиента\n  400 Bad Request  — неверный запрос (невалидные данные)\n  401 Unauthorized — не аутентифицирован\n  403 Forbidden    — аутентифицирован, но нет доступа\n  404 Not Found    — ресурс не найден\n  409 Conflict     — конфликт (например, email уже занят)\n  422 Unprocessable — данные валидны по формату, но не по логике\n\n5xx — ошибка сервера\n  500 Internal Server Error — что-то сломалось на сервере\n  503 Service Unavailable   — сервис временно недоступен\n",[44,286,284],{"__ignoreMap":46},[15,288,289,290,293,294,297],{},"Типичная ошибка новичков — возвращать ",[44,291,292],{},"200 OK"," с телом ",[44,295,296],{},"{\"error\": \"not found\"}",". Это нарушает контракт REST: клиент смотрит на статус код, а не парсит тело чтобы понять успех это или ошибка.",[19,299],{},[22,301,303],{"id":302},"что-такое-restful-api","Что такое RESTful API",[15,305,306,309],{},[29,307,308],{},"RESTful API"," — это веб-API, который следует принципам REST. Приставка \"-ful\" означает \"в полной мере\". Если API соответствует принципам Филдинга — его можно назвать RESTful.",[15,311,312],{},"На практике термины \"REST API\" и \"RESTful API\" используются как синонимы — разница только в степени строгости соответствия принципам.",[19,314],{},[22,316,318],{"id":317},"rest-vs-не-rest-на-примере-todo-api","REST vs не REST — на примере Todo API",[15,320,321],{},"Разница становится понятнее на конкретных примерах. Вот хорошие и плохие варианты для нашего Todo API:",[37,323,326],{"className":324,"code":325,"language":42},[40],"\u002F\u002F ❌ Не REST — действие в URL, игнорирование методов\nPOST \u002FgetTodos\nPOST \u002FcreateTodo\nPOST \u002FdeleteTodo?id=1\nPOST \u002FmarkTodoAsDone?id=1\nGET  \u002Ftodo\u002Fdelete\u002F1\n\n\u002F\u002F ✅ REST — URL это ресурс, метод это действие\nGET    \u002Fapi\u002Ftodos\nPOST   \u002Fapi\u002Ftodos\nDELETE \u002Fapi\u002Ftodos\u002F1\nPUT    \u002Fapi\u002Ftodos\u002F1\n",[44,327,325],{"__ignoreMap":46},[37,329,332],{"className":330,"code":331,"language":42},[40],"\u002F\u002F ❌ Не REST — всегда 200, ошибка в теле\nHTTP 200 OK\n{\"success\": false, \"error\": \"todo not found\"}\n\n\u002F\u002F ✅ REST — статус код отражает результат\nHTTP 404 Not Found\n{\"error\": \"todo not found\"}\n",[44,333,331],{"__ignoreMap":46},[37,335,338],{"className":336,"code":337,"language":42},[40],"\u002F\u002F ❌ Не REST — глагол в URL\nPOST \u002Fapi\u002Ftodos\u002F1\u002FmarkDone\nPOST \u002Fapi\u002Ftodos\u002F1\u002Farchive\nGET  \u002Fapi\u002FgetAllTodos\n\n\u002F\u002F ✅ REST — глагол выражен методом, URL — существительное\nPUT  \u002Fapi\u002Ftodos\u002F1        (с телом {\"done\": true})\nPUT  \u002Fapi\u002Ftodos\u002F1        (с телом {\"archived\": true})\nGET  \u002Fapi\u002Ftodos\n",[44,339,337],{"__ignoreMap":46},[19,341],{},[22,343,345],{"id":344},"когда-rest-не-подходит","Когда REST не подходит",[15,347,348],{},"REST хорош для большинства задач, но не универсален. Есть случаи когда выбирают другой подход:",[15,350,351,354],{},[29,352,353],{},"GraphQL"," — когда клиенту нужна гибкость в выборе полей. Вместо нескольких REST-запросов — один запрос с описанием нужных данных. Популярен в мобильных приложениях где важен трафик.",[15,356,357,360],{},[29,358,359],{},"gRPC"," — когда нужна высокая производительность и строгая типизация между сервисами. Использует бинарный протокол (protobuf) вместо JSON. Стандарт для межсервисного взаимодействия в микросервисах.",[15,362,363,366],{},[29,364,365],{},"WebSocket"," — когда нужна двусторонняя связь в реальном времени: чат, онлайн-игры, live-уведомления. REST работает по схеме запрос-ответ, WebSocket держит постоянное соединение.",[15,368,369],{},"На собеседовании на позицию backend-разработчика достаточно понимать REST и уметь объяснить почему выбирают альтернативы — это уже уровень осознанного выбора инструмента.",[19,371],{},[22,373,375],{"id":374},"вопросы-на-собеседовании","Вопросы на собеседовании",[15,377,378,381,384],{},[29,379,380],{},"Q: Что такое API? Чем веб-API отличается от любого другого API?",[382,383],"br",{},"\nA: API — интерфейс через который одна программа общается с другой: набор правил и контрактов взаимодействия. Веб-API — частный случай: интерфейс доступный по сети через HTTP. Любая библиотека тоже предоставляет API — в виде функций и классов, но не через сеть.",[15,386,387,390,392],{},[29,388,389],{},"Q: Что такое REST? Это протокол или технология?",[382,391],{},"\nA: Ни то ни другое. REST — архитектурный стиль: набор принципов проектирования веб-API, описанных Роем Филдингом в 2000 году. Главные: клиент-сервер, stateless, единый интерфейс (ресурсы в URL, действия в HTTP-методах), кешируемость.",[15,394,395,398,400],{},[29,396,397],{},"Q: Что значит stateless в контексте REST?",[382,399],{},"\nA: Сервер не хранит состояние между запросами. Каждый запрос самодостаточен — содержит всю информацию необходимую для обработки: идентификацию пользователя, параметры, данные. Это делает систему масштабируемой: любой сервер может обработать любой запрос.",[15,402,403,406,408,409,411,412,414,415,417,418,420],{},[29,404,405],{},"Q: Чем PUT отличается от PATCH?",[382,407],{},"\nA: ",[44,410,234],{}," заменяет ресурс целиком — нужно передать все поля. ",[44,413,246],{}," обновляет частично — только изменённые поля. ",[44,416,234],{}," идемпотентен: повторный вызов с теми же данными не меняет результат. ",[44,419,246],{}," технически нет, хотя на практике часто реализуют идемпотентно.",[15,422,423,429,431,432,293,435,153],{},[29,424,425,426,428],{},"Q: Почему нельзя возвращать 200 OK с телом ",[44,427,296],{},"?",[382,430],{},"\nA: Нарушает контракт REST и HTTP. Клиент (браузер, мобильное приложение, другой сервис) смотрит на статус код чтобы понять успех или ошибка — без парсинга тела. 200 означает успех. Middleware, прокси, CDN тоже ориентируются на статус коды. Правильно: ",[44,433,434],{},"404 Not Found",[44,436,296],{},[15,438,439,442,408,444,447,448,451],{},[29,440,441],{},"Q: Чем отличаются 401 и 403?",[382,443],{},[44,445,446],{},"401 Unauthorized"," — пользователь не аутентифицирован: не передал токен или токен невалидный. Буквально \"мы не знаем кто ты\". ",[44,449,450],{},"403 Forbidden"," — пользователь аутентифицирован, но у него нет прав на это действие. \"Мы знаем кто ты, но тебе нельзя\".",[15,453,454,457,459,460,462,463,462,465,467,468,470,471,473],{},[29,455,456],{},"Q: Что такое идемпотентность? Какие HTTP-методы идемпотентны?",[382,458],{},"\nA: Операция идемпотентна если повторное выполнение с теми же параметрами даёт тот же результат. ",[44,461,208],{},", ",[44,464,234],{},[44,466,258],{}," — идемпотентны. ",[44,469,221],{}," — нет: каждый вызов создаёт новый ресурс. ",[44,472,246],{}," — зависит от реализации.",[15,475,476,479,481],{},[29,477,478],{},"Q: Когда REST не лучший выбор?",[382,480],{},"\nA: Когда нужна гибкость запросов от клиента — GraphQL. Когда нужна высокая производительность и строгая типизация между сервисами — gRPC. Когда нужна двусторонняя связь в реальном времени — WebSocket.",{"title":46,"searchDepth":483,"depth":483,"links":484},2,[485,486,493,496,497,498,499],{"id":24,"depth":483,"text":25},{"id":67,"depth":483,"text":68,"children":487},[488,490,491,492],{"id":85,"depth":489,"text":86},3,{"id":98,"depth":489,"text":99},{"id":114,"depth":489,"text":115},{"id":165,"depth":489,"text":166},{"id":174,"depth":483,"text":175,"children":494},[495],{"id":276,"depth":489,"text":277},{"id":302,"depth":483,"text":303},{"id":317,"depth":483,"text":318},{"id":344,"depth":483,"text":345},{"id":374,"depth":483,"text":375},"intermediate","md",{},"web",true,"todo-project","\u002F05-web\u002F03-rest-api","echo",{"title":5,"description":17},"rest-api","05-web\u002F03-rest-api\u002Findex",[73,31,512,276,513,514],"CRUD","версионирование","собеседование","1hlOnyzte6iQdiz_gH3LK_L4On7XYHe2TZneDXbFFZw",1776289836149]