В каких местах HTTP-запроса можно передать полезную нагрузку с клиента на сервер?
Что проверяют
Понимаете ли вы устройство HTTP-запроса целиком, а не только «GET с параметрами и POST с JSON». Python-бэкендера следом спрашивают, как эти части достаются в Django, Flask или FastAPI и где у каждой ограничения.
Как отвечать
Данные от клиента приезжают в пяти местах:
- путь:
/users/42/orders, идентификатор ресурса. Во всех трёх фреймворках это параметр маршрута; - строка запроса:
?page=2&sort=date, фильтры и пагинация.request.GETв Django,request.argsво Flask,Queryв FastAPI; - заголовки:
Authorizationс токеном,Accept-Language, собственные вродеX-Request-Id. Этоrequest.headers, в FastAPIHeader; - куки: технически тоже заголовок
Cookie, но фреймворки отдают их отдельно:request.COOKIES,request.cookies,Cookie; - тело: JSON, форма
application/x-www-form-urlencoded,multipart/form-dataдля файлов или сырые байты. В Djangorequest.body,request.POST,request.FILES, во Flaskrequest.get_json(),request.form,request.files, в FastAPI модель Pydantic,FormиFile(для двух последних нужен пакетpython-multipart).
Фрагмент после # на сервер не уходит вовсе.
Стандарт не задаёт предел длины URL: RFC 9110 советует поддерживать хотя бы 8000 октетов, а реальный предел ставят сервер и прокси. Тело тоже ограничено, у nginx client_max_body_size по умолчанию 1 МБ. Тело у GET по RFC 9110 не имеет определённого смысла, часть прокси его отбрасывает, а fetch в браузере такой запрос не отправит и выбросит TypeError.
Где спотыкаются
Говорят, что POST безопасен, а GET нет. Без TLS оба идут открытым текстом, с HTTPS оба зашифрованы. Разница в другом: строка запроса оседает в логах, истории браузера и заголовке Referer, поэтому токены и пароли туда не кладут.
Утверждают, что размер тела POST не ограничен. Ограничен, и первым обычно упирается nginx с ответом 413.
Путают метаданные с полезной нагрузкой: Content-Type описывает тело, а не несёт данные. И забывают про заголовки как канал, хотя токен авторизации едет именно там.