Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Проверка данных

Клиенту нельзя доверять: он может прислать пустой заголовок, слишком короткий текст или сломанный JSON. Валидация — проверка входных данных до того, как они попадут в хранилище. В Javalin для этого есть валидаторы: методы bodyValidator, queryParamAsClass, pathParamAsClass и headerAsClass возвращают объект Validator, к которому добавляются правила.

Как работает валидатор

  1. Метод вида ...AsClass или bodyValidator создаёт валидатор и пробует превратить строку или JSON в нужный тип.
  2. Методы check(условие, "сообщение") добавляют правила.
  3. Метод get() возвращает значение или бросает ValidationException, если хоть одно правило нарушено.

ValidationException Javalin сам превращает в ответ 400 со списком ошибок в JSON.

Проверка тела запроса

Замените bodyAsClass в маршруте создания поста на bodyValidator:

// src/main/java/com/example/blog/Main.java
config.routes.post("/posts", ctx -> {
    NewPost data = ctx.bodyValidator(NewPost.class)
            .check(p -> p.title() != null && !p.title().isBlank(), "Нужен заголовок")
            .check(p -> p.body() != null && p.body().length() >= 5, "Текст слишком короткий")
            .get();
    ctx.status(HttpStatus.CREATED).json(store.create(data));
});

Каждое правило получает готовый объект NewPost и возвращает true, если всё в порядке. Отправим неверный пост:

curl -i -X POST http://localhost:8080/posts \
     -d '{"title":"","body":"abc","author":"Олег"}'
HTTP/1.1 400 Bad Request
Content-Type: application/json

{"REQUEST_BODY":[{"message":"Нужен заголовок","args":{},"value":{"title":"","body":"abc","author":"Олег"}},{"message":"Текст слишком короткий","args":{},"value":{"title":"","body":"abc","author":"Олег"}}]}

Javalin проверил все правила и вернул обе ошибки сразу. Ключ REQUEST_BODY означает, что ошибка в теле запроса.

Проверка параметров

Те же правила работают с параметрами. Ограничим размер страницы в поиске:

// src/main/java/com/example/blog/Main.java
int limit = ctx.queryParamAsClass("limit", Integer.class)
        .check(n -> n >= 1 && n <= 50, "Лимит должен быть от 1 до 50")
        .getOrDefault(10);

На ?limit=100 сервер ответит 400 и {"limit":[{"message":"Лимит должен быть от 1 до 50","args":{},"value":100}]}, а без параметра подставит 10.

Методы получения значения

МетодЕсли значения нетЕсли правило нарушено
get()400, ошибка NULLCHECK_FAILED400
getOrDefault(10)Значение по умолчанию400
getOrNull()null400

Частая ошибка

ctx.bodyAsClass не проверяет данные: на сломанный JSON, например {"title":"x" без закрывающей скобки, клиент получает 500 Server Error, а в логе — JsonEOFException: Unexpected end-of-input. Так выглядит ошибка сервера, хотя ошибся клиент. С bodyValidator тот же запрос получает правильный ответ:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{"REQUEST_BODY":[{"message":"DESERIALIZATION_FAILED","args":{},"value":"{\"title\":\"x\""}]}

Для данных от клиента используйте bodyValidator.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.