Какими способами можно передать данные в REST эндпоинт
Что проверяют
Знаете ли вы, какая часть HTTP-запроса для каких данных предназначена и как Spring раскладывает её по параметрам метода. Следом часто спрашивают, можно ли отправить тело в GET и чем PUT отличается от PATCH.
Как отвечать
Данные в запросе живут в нескольких местах, и у каждого своя аннотация Spring MVC:
- путь: идентификатор ресурса,
/users/42, читается через@PathVariable; - query string: фильтры, сортировка, пагинация.
@RequestParamпо умолчанию обязателен, без него придёт 400, пока не укажетеrequired = falseилиdefaultValue. Много параметров удобно собрать в объект; - тело: сущность целиком, обычно JSON.
@RequestBodyплюс Jackson, с@Validвключается Bean Validation изjakarta.validation. Формат задаётContent-Type, ограничить его можно черезconsumes; - формы и файлы:
application/x-www-form-urlencodedчерез@ModelAttributeили@RequestParam,multipart/form-dataчерез@RequestPartиMultipartFile. Лимит на файл по умолчанию 1 МБ, его меняют вspring.servlet.multipart.max-file-size; - заголовки и куки: метаданные, а не бизнес-данные.
Authorization,Accept-Language,Idempotency-Keyчитают через@RequestHeader, куки через@CookieValue.
В JAX-RS те же места: @PathParam, @QueryParam, @FormParam, @HeaderParam, @CookieParam.
Про методы: GET и DELETE обычно без тела, POST создаёт, PUT заменяет ресурс целиком и идемпотентен, PATCH меняет часть полей. Тело в GET стандарт не запрещает, но и смысла ему не задаёт, прокси и часть клиентов его отбрасывают, поэтому сложный поиск делают через POST на /search.
Где спотыкаются
Передают токены, пароли и персональные данные в query string. Они оседают в логах сервера, истории браузера и заголовке Referer, HTTPS тут не помогает.
Не различают PUT и PATCH и отправляют PUT с одним полем. Сервер вправе затереть остальные поля значением null.
Ставят два @RequestBody в один метод, чтобы разобрать JSON на части. Тело читается из потока один раз, поэтому нужен один DTO со всеми полями.