Что такое API и REST: введение в FastAPI для начинающих
Понять, что такое API, REST, HTTP-методы и JSON — и подготовиться к первому приложению на FastAPI.
Редакция Питоники
Представьте: вы написали на Python скрипт, который считает выручку кофейни за день. Скрипт лежит у вас на ноутбуке. А менеджеру нужны эти цифры в его мобильном приложении, курьеру — в его системе, аналитику — в дашборде. Три человека, три устройства, один набор данных. Рассылать каждому Excel по почте — тупик. Выход один: поднять сервер, который по запросу отдаёт данные в аккуратном виде. Такой сервер и называется API — и весь этот курс мы будем строить его на FastAPI, самом быстрорастущем веб-фреймворке Python.
Этот урок — фундамент. Без него дальше будет туман: вы сможете копировать код из документации, но не поймёте, почему он работает. А с фундаментом вы будете видеть за каждой строчкой кода обычный HTTP-запрос. Поехали.
Что такое API простыми словами
API (Application Programming Interface, программный интерфейс приложения) — это набор правил, по которым одна программа может попросить другую программу сделать что-то или отдать данные. Ключевое слово здесь — «попросить», а не «залезть внутрь». API — это договор о том, какие запросы можно делать и что вы получите в ответ.
Классическая метафора — официант в ресторане. Вы (клиент) не заходите на кухню (сервер) и не сами варите борщ. Вы говорите официанту: «Один борщ» — он передаёт заказ на кухню и приносит готовое. Меню — это и есть API-документация: список блюд (эндпоинтов), которые кухня готова готовить. Если вы попросите то, чего нет в меню, официант не станет угадывать — он откажет.
Метафора хороша для старта, но живой разработчик должен видеть за ней технику. Когда мобильное приложение «Кофе у дома» показывает вам меню, оно не хранит напитки внутри себя. Оно отправляет HTTP-запрос на адрес вроде https://api.coffee.ru/products и получает обратно ответ в формате JSON. Сервер при этом может быть написан на чём угодно: Python, Go, Java — клиенту всё равно, потому что договор (API) не меняется. Именно такой сервер вы и научитесь писать на FastAPI.
Клиент и сервер: кто с кем разговаривает
В любой работе с API участвуют две стороны. Клиент — тот, кто отправляет запрос: браузер, мобильное приложение, другой сервер, ваш Python-скрипт или консольная утилита curl. Сервер — тот, кто запрос получает, обрабатывает и возвращает ответ. Это называется клиент-серверной архитектурой, и это первая из шести архитектурных черт, которые вместе образуют стиль REST.
Важно, что клиент и сервер ничего не знают о внутренностях друг друга. Фронтендеру, который рисует каталог товаров, не нужно знать, что за база данных у вас — PostgreSQL или просто список в памяти. Ему важно одно: отправить правильный запрос на правильный адрес и получить правильный JSON. Это разделение — причина, по которой API живут десятилетиями, пока приложения вокруг них переписывают по три раза.
Как выглядит HTTP-запрос изнутри
HTTP — протокол, язык, на котором клиент и сервер ведут переписку. Запрос — это обычный текст, и его можно показать целиком. Вот что отправляет клиент, когда хочет узнать информацию о товаре с номером 42:
GET /products/42 HTTP/1.1
Host: coffee.example.com
Accept: application/json
Разберём по косточкам. Первая строка — самая важная. GET — это HTTP-метод, действие, которое клиент просит выполнить. /products/42 — путь, то есть какой ресурс интересует. HTTP/1.1 — версия протокола. Дальше идут заголовки (Host, Accept) — служебная информация: кому адресован запрос и в каком формате клиент хочет ответ. У запроса может быть и тело — например, у POST-запроса «создать товар» в теле лежат данные нового товара.
Запомните эту четвёрку: метод, путь, заголовки, тело. Любая веб-разработка — это всего лишь их комбинации. FastAPI всю первую половину курса учит вас именно ими управлять.
Ответ сервера: статус, заголовки и тело
Сервер отвечает в таком же текстовом формате:
HTTP/1.1 200 OK
Content-Type: application/json
{"id": 42, "name": "Эспрессо", "price": 199.9}
Первая строка ответа — статус-код с человеческой подписью. 200 OK означает «всё получилось, вот данные». Тело ответа — JSON с данными о товаре. Заголовок Content-Type: application/json честно предупреждает: внутри JSON, а не HTML. Клиент по этому заголовку понимает, как разбирать тело.
HTTP-методы: глаголы, на которых работает REST
Если путь отвечает на вопрос «с чем работаем», то метод — «что делаем». В REST четыре главных метода, и вы будете пользоваться ими каждый день:
| Метод | Что делает | Пример |
|---|---|---|
| GET | Читает данные, ничего не меняет | GET /products — список товаров |
| POST | Создаёт новый ресурс | POST /products — добавить товар |
| PUT | Обновляет ресурс целиком | PUT /products/42 — заменить данные товара |
| DELETE | Удаляет ресурс | DELETE /products/42 — убрать товар |
Заметьте: чтобы удалить товар с номером 42, клиент отправляет DELETE на путь /products/42, а не на /deleteProduct42. Действие закодировано в методе, а не в адресе. Это непривычно после процедурного программирования, где у вас были функции create_user() и delete_user(), но именно так устроен REST — и на собеседованиях любят спрашивать, почему.
У GET тела нет — читать нечего передавать. А вот POST-запрос несёт данные нового ресурса прямо в теле, сразу после заголовков:
POST /products HTTP/1.1
Host: coffee.example.com
Content-Type: application/json
{"name": "Латте", "price": 250}
Ресурсы и URL: как думать как REST-дизайнер
Ресурс — это любая сущность, с которой работает ваш API: товар, заказ, пользователь, фотография. Каждый ресурс получает свой URL, и URL строят как существительные во множественном числе. Хорошо спроектированный API читается как обычная фраза:
GET /products— «покажи товары»GET /orders/17— «покажи заказ номер 17»GET /users/5/orders— «покажи заказы пользователя номер 5»POST /products— «создай товар» (данные нового товара — в теле запроса)
Коды ответов: 2xx, 4xx, 5xx
Статус-код — первая строка ответа, три числа, которые говорят о результате одним взглядом. Первая цифра — класс: 2xx — успех, 3xx — перенаправление, 4xx — виноват клиент, 5xx — виноват сервер. Половина багов в API находится именно по коду ответа, поэтому вот таблица кодов, которые вы будете видеть чаще всего:
| Код | Название | Когда возникает |
|---|---|---|
| 200 | OK | Обычный успешный ответ на GET, PUT, DELETE |
| 201 | Created | Ресурс успешно создан — правильный ответ на POST |
| 204 | No Content | Успех без тела ответа — так отвечает DELETE |
| 404 | Not Found | Ресурса по этому пути не существует |
| 422 | Unprocessable Entity | Данные в запросе не прошли валидацию |
| 500 | Internal Server Error | Ошибка в вашем коде на сервере |
Код 422 заслуживает отдельного внимания: FastAPI возвращает его, когда прислали кривые данные — например, цену словом «дорого» вместо числа. Это фирменный признак фреймворка: валидация встроена в него так глубоко, что битые запросы отсекаются ещё до вашего кода. В третьем и четвёртом уроках мы будем ловить 422 вживую и учиться читать его структуру.
JSON: язык, на котором говорят все API
JSON (JavaScript Object Notation) — текстовый формат данных, который серверы отдают почти в каждом ответе REST API. Он компактен, читается человеком и парсится любым языком программирования. Выглядит так: {"name": "Эспрессо", "price": 199.9} — объект в фигурных скобках, ключи в двойных кавычках, значения — строки, числа, true/false, null, массивы или вложенные объекты.
В Python есть встроенный модуль json, который превращает словари в JSON-строки (сериализация) и обратно (десериализация). Это не FastAPI — это стандартная библиотека, и она работает прямо в нашем интерактивном редакторе. Попробуйте:
import json
# Данные товара, как их хранит Python
product = {"id": 42, "name": "Эспрессо", "price": 199.9}
# Сериализация: Python -> строка JSON
as_json = json.dumps(product, ensure_ascii=False)
print(as_json)
print(type(as_json).__name__)
{"id": 42, "name": "Эспрессо", "price": 199.9}
strОбратите внимание на тип: после json.dumps у вас уже не словарь, а строка. Именно она летит по сети. Параметр ensure_ascii=False разрешает кириллицу в читаемом виде — без него «Эспрессо» превратилось бы в Эспрессо, и это тоже валидный JSON, просто глазам больно.
Обратная операция — json.loads: из строки, которую прислал сервер, получается питоновский объект. Важно следить, какие типы JSON даёт на выходе: false становится False, null — None, а целое и дробное число различаются:
import json
# Строка, которую прислал сервер
raw = '{"city": "Москва", "temp": 12, "rain": false, "wind": null}'
data = json.loads(raw)
print(data["city"], data["temp"])
print("rain:", data["rain"], "тип:", type(data["rain"]).__name__)
print("wind:", data["wind"], "тип:", type(data["wind"]).__name__)
print("всего ключей:", len(data))
Москва 12 rain: False тип: bool wind: None тип: NoneType всего ключей: 4
Реальные ответы API почти всегда вложены: заказ содержит список позиций, позиция — ссылку на товар. JSON справляется с этим без усилий — объекты и массивы вкладываются на любую глубину:
import json
# Заказ: есть вложенные данные - список позиций
order = {
"id": 17,
"customer": "Анна",
"items": ["Эспрессо", "Круассан"],
"total": 349.9,
}
raw = json.dumps(order, ensure_ascii=False)
print(raw)
print("позиций в заказе:", len(json.loads(raw)["items"]))
{"id": 17, "customer": "Анна", "items": ["Эспрессо", "Круассан"], "total": 349.9}
позиций в заказе: 2FastAPI делает обе операции за вас автоматически: вы возвращаете из функции словарь — клиент получает JSON; клиент присылает JSON — вам в функцию приходит готовый объект. Но понимать, что происходит под капотом, необходимо: когда однажды в ответе окажется не то поле, вы будете искать проблему не там, где она кажется.
Заглянем под капот чуть глубже. Что вообще делает веб-фреймворк, получив запрос? Он разбирает первую строку, достаёт путь и параметры и решает, какую вашу функцию вызвать. Для простого GET-запроса это буквально пара split и partition:
# Имитация разбора первой строки HTTP-запроса,
# которую выполняет любой веб-фреймворк
line = "GET /products?limit=5 HTTP/1.1"
method, path_and_query, protocol = line.split(" ")
path, _, query = path_and_query.partition("?")
print("Метод:", method)
print("Путь:", path)
print("Query-параметры:", query)
print("Протокол:", protocol)
Метод: GET Путь: /products Query-параметры: limit=5 Протокол: HTTP/1.1
То, что вы видите в этом примере, — зародыш маршрутизации. В настоящем FastAPI всё это разрослось в умный сопоставитель путей, конвертер типов и генератор документации, но принцип не меняется с 1991 года.
Почему FastAPI: четыре причины выбрать его для первого API
На Python есть минимум три популярных способа сделать API: Django REST Framework, Flask и FastAPI. Я почти всегда выбираю FastAPI для новых проектов, и вот почему — по нарастающей важности.
- Скорость выполнения. FastAPI построен на ASGI-сервере uvicorn и асинхронной модели — в бенчмарках он стабильно быстрее классического Flask, а местами на порядок быстрее Django. Фраза «FastAPI быстрый» — не маркетинг, а буквальное название.
- Скорость разработки. Проверка типов через pydantic и автодополнение в IDE ловят ваши ошибки до запуска сервера. Опечатка в имени поля не пролетит молча — она сломается на этапе написания.
- Автодокументация. Каждый эндпоинт сам попадает в интерактивную документацию Swagger по адресу
/docs. Документация, которая всегда актуальна, — редкость в индустрии, а у вас она будет бесплатно. - Валидация из коробки. Пришедшие данные проверяет pydantic: строку вместо числа, цену со знаком минус, отсутствующее обязательное поле — всё это отсекается до вашего кода с понятной ошибкой 422.
Для сравнения посмотрите на ту же задачу «отдать товар по пути /products/42» во Flask — она пригодится вам, если решите пройти наш самоучитель Flask:
from flask import Flask, jsonify
app = Flask(__name__)
@app.get("/products/42")
def get_product():
# Flask требует явного jsonify для правильных заголовков
return jsonify({"id": 42, "name": "Эспрессо", "price": 199.9})
Разница в двух строчках, но она символична: во Flask вы вручную оборачиваете словарь в jsonify, а FastAPI принимает обычный dict и сам сериализует его. Чем сложнее API, тем сильнее этот разрыв в пользу FastAPI — особенно на валидации. А если вы пришли из Django, знайте: DRF — отличный, но тяжёлый инструмент, где чтобы получить JSON, нужно описать сериализаторы, вьюсеты и роутеры. FastAPI сокращает этот путь до декоратора над функцией.
FastAPI — это современный, быстрый (высокопроизводительный) веб-фреймворк для построения API на Python, основанный на стандартных подсказках типов.
— Себастьян Рамирес, автор FastAPI
Нужен ли REST-фундамент, если фреймворк всё сделает сам?
Короткий ответ: да, и вот тривиальный пример, почему. В FastAPI вы пишете @app.get("/products/{id}") — и в документации появляется красивый список. Но когда в продакшене фронтендер спросит: «Почему на PUT /products/42 вы возвращаете 200, а на создание — 200 вместо 201?» — фреймворк за вас не ответит. REST — это профессиональный язык, на котором общаются бэкендеры, фронтендеры и мобильщики. С ним вы понимаете чужие API, читаете документацию мессенджеров и платёжных систем, спорите о дизайне осмысленно.
Дешёвая проверка на понимание REST: спроектируйте API для библиотеки. Ресурсы — книги (/books) и читатели (/readers). Как выглядит «записать книгу номер 7 за читателем номер 3»? Вариант /lendBook?book=7&reader=3 — не REST. REST-подход: создать ресурс «выдача» — POST /loans с телом {"book_id": 7, "reader_id": 3}. Если вы почувствовали разницу — вы уже мыслите как REST-дизайнер.
Что дальше: от теории к первому коду
Подведём баланс того, что вы уже знаете. API — договор между клиентом и сервером. Запрос — это метод, путь, заголовки, тело. Ответ — это статус, заголовки, JSON. Ресурсы — существительные в URL, действия — в HTTP-методах. FastAPI берёт на себя сериализацию, валидацию и документацию.
Во втором уроке соберём первое приложение на FastAPI: включим компьютер в роли сервера, установим FastAPI и uvicorn, напишем файл main.py с первым эндпоинтом @app.get("/"), запустим его командой uvicorn main:app --reload и откроем живую документацию Swagger. Вы увидите свой первый 200 OK — а заодно разберёте типичные ошибки первого запуска. Один нюанс: сервер целиком в браузерной песочнице не поднимается, поэтому HTTP-часть мы показываем с точным ожидаемым выводом — зато модели pydantic, сердце валидации FastAPI, будут запускаться прямо на странице, начиная с урока 4 про pydantic-модели.
Если хочется параллельно освежить синтаксис Python — декораторы, аннотации типов, словари — загляните в базовый курс. А для практиков в данных будет полезно знать, что API часто обслуживают именно модели машинного обучения: например, сервис, обученный в уроках по NumPy, в итоге оборачивается в FastAPI-эндпоинт и начинает отдавать предсказания по HTTP. Этот урок — первая ступень из десяти; весь маршрут целиком — самоучитель FastAPI.
Сначала предскажи ответ в голове — это главный навык программиста.
import json
data = {"name": "Латте", "price": 250, "hot": True}
print(json.dumps(data, ensure_ascii=False))
line = "DELETE /orders/17 HTTP/1.1"
method, path_and_query, protocol = line.split(" ")
print(method, len(path_and_query))
1. Что такое API одним предложением?
2. Каким HTTP-методом в REST правильно удалять товар с id 42?
3. Клиент отправил данные нового товара, но поле «цена» не прошло проверку. Какой статус вернёт FastAPI?
4. Что произойдёт после json.loads('{"temp": 12}')?
5. Почему GET-запрос считается «безопасным» методом?
Соберите JSON-ответ сервера для товара «Капучино» и прочитайте его обратно, как это делает FastAPI: сериализуйте словарь в строку JSON (с кириллицей в читаемом виде), затем десериализуйте её и выведите цену и тип поля в_stock.
Что такое API простыми словами?
API — это договор между двумя программами: первая отправляет запрос по правилам (адрес, метод, данные), вторая возвращает предсказуемый ответ. Как меню в ресторане: видно, что можно заказать, и что за это будет.
Чем REST API отличается от обычного сайта?
Сайт отдаёт HTML — разметку для человека и браузера. REST API отдаёт структурированные данные (обычно JSON) для программы: мобильного приложения, фронтенда или другого сервера. Один и тот же бэкенд может обслуживать и то, и другое.
Почему FastAPI называют быстрым?
В двух смыслах: он быстрый по производительности (работает поверх ASGI-сервера uvicorn и поддерживает async/await) и быстрый в разработке (типы, автодокументация Swagger и валидация pydantic экономят часы).
Нужно ли знать базы данных, чтобы начать с FastAPI?
Нет. Первые пять уроков курса обходятся данными в памяти — списками и словарями Python. Настоящая база данных (SQLite через SQLAlchemy) подключается в седьмом уроке, когда CRUD уже освоен.
Чем метод GET отличается от POST в REST?
GET читает данные и тела не имеет — передавать нечего. POST создаёт новый ресурс и несёт его данные в теле запроса, например POST /products с {"name": "Латте", "price": 250}. А действие кодируется методом, а не адресом: DELETE /products/42, а не /deleteProduct42.
Понравился урок? Сошлитесь на него
«Это разделение — причина, по которой API живут десятилетиями, пока приложения вокруг них переписывают по три раза.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что читать дальше
FastAPI · Урок 2
Первое приложение на FastAPI: маршруты, uvicorn и Swagger
Устанавливаем FastAPI, пишем первый эндпоинт, запускаем сервер uvicorn и открываем Swagger — документацию, которая пишет себя сама.
Flask · Урок 1
Что такое Flask: знакомство с микрофреймворком
Первый урок самоучителя Flask: как устроен веб, зачем нужен WSGI, чем микрофреймворк отличается от Django — и как за семь строк получить работающий сайт.
FastAPI · Урок 3
Параметры запросов: path, query и валидация в FastAPI
Осваиваем path- и query-параметры FastAPI: типы, дефолты, валидация через Query и чтение ошибки 422.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
Pandas · Урок 1
Что такое Pandas и как установить через pip: первые Series и DataFrame
Первая таблица DataFrame в библиотеке pandas, умный столбец Series и быстрый осмотр данных через head, info и describe — старт сквозного анализа данных интернет-магазина.
pandas для начинающихчто такое dataframe
json · Урок 1
Что такое JSON и зачем он Python: первый json.dumps
Первое превращение словаря в json-строку одной командой: import json, json.dumps и честный взгляд на кракозябры в выводе — всё исполняется прямо на странице.
json python что эточто такое json
FastAPI · Урок 5
CRUD на FastAPI: POST, PUT, PATCH и DELETE методы
Строим полный CRUD на FastAPI: POST со статусом 201, PUT с защитой от 404, PATCH и DELETE — и собираем мини-сервис задач целиком.
fastapi crudpost запрос fastapi
Проверьте знания по FastAPI
В челлендже — 20 задач по FastAPI, по 2 из каждого урока этого раздела. Формат: фрагмент кода и четыре варианта — что напечатает. После ответа — вердикт и объяснение со ссылкой на урок-источник.
Тест по FastAPI: 20 задач