Skip to content

Validation

The framework includes a validation engine inspired by Laravel. It provides reusable rule classes for checking request data.

Available Rules

Each rule is a class in framework::support::validation::rules.

RuleDescriptionExample
requiredField must be present and non-emptyrules::required()
stringValue must be a stringrules::string()
integerValue must be an integerrules::integer()
numericValue must be numeric (int or float)rules::numeric()
booleanValue must be true/falserules::boolean()
arrayValue must be a JSON arrayrules::array()
objectValue must be a JSON objectrules::object()
emailValue must be a valid emailrules::email()
ipValue must be a valid IP addressrules::ip()
urlValue must be a valid URLrules::url()
uuidValue must be a valid UUIDrules::uuid()
regex(pattern)Value must match the regexrules::regex("^[a-z]+$")
min(n)Minimum length or numeric valuerules::min(3)
max(n)Maximum length or numeric valuerules::max(255)
size(n)Exact length or numeric valuerules::size(10)
in(values...)Must be one of the listed valuesrules::in({"a", "b"})
not_in(values...)Must not be one of the listed valuesrules::not_in({"x", "y"})
alphaMust contain only lettersrules::alpha()
alpha_numMust contain only letters and numbersrules::alpha_num()
alpha_dashLetters, numbers, dashes, underscoresrules::alpha_dash()
confirmedField must have matching _confirmation fieldrules::confirmed()
same(field)Must match another fieldrules::same("password")
different(field)Must differ from another fieldrules::different("old_password")
nullableField can be null (bypasses other rules)rules::nullable()
presentField must be present in the datarules::present()

Rule Base Class

Every rule extends framework::support::validation::rule and implements two methods:

cpp
#include <framework/support/validation/rules.hpp>

// bool validate(const std::string& attribute, const boost::json::value& value, const boost::json::object& data)
//   Returns true if the value passes the rule.
//   `attribute` is the field name, `data` is the full object (for cross-field rules).
//
// std::string message(const std::string& attribute) const
//   Returns the error message for when validation fails.

The is_implicit() method can be overridden (returns false by default). Implicit rules like required and nullable are checked even when the field is absent.


Using Rules Directly

Instantiate rules and call validate() on individual values.

cpp
#include <framework/support/validation/rules.hpp>

using namespace framework::support::validation;

rules::required required_rule;
rules::email email_rule;
rules::min min_len(3);
rules::max max_len(255);

auto& obj = body.as_object();

bool valid = required_rule.validate("name", obj.at("name"), obj);
bool is_email = email_rule.validate("email", obj.at("email"), obj);

Building a Validator for HTTP Routes

For HTTP routes, the validator is a function that receives the full http_request and returns a pair: {is_valid, errors_map}.

cpp
using namespace framework;
using namespace framework::clients::http;

auto user_validator = [](const http_request& req)
    -> std::pair<bool, std::unordered_map<std::string, std::vector<std::string>>> {

    if (!req.body_.has_value()) {
        return {false, {{"body", {"Request body is required"}}}};
    }

    auto& obj = req.body_->as_object();
    std::unordered_map<std::string, std::vector<std::string>> errors;

    // Use rule classes to validate
    rules::required required;
    rules::email email;

    if (required.is_implicit() || obj.contains("name")) {
        if (!required.validate("name", obj.contains("name") ? obj.at("name") : nullptr, obj)) {
            errors["name"].push_back(required.message("name"));
        }
    }
    if (obj.contains("email") && !email.validate("email", obj.at("email"), obj)) {
        errors["email"].push_back(email.message("email"));
    }

    if (!errors.empty()) {
        return {false, errors};
    }
    return {true, {}};
};

// Attach the validator to a route
app.register_endpoint(
    http_verb_t::post,
    "/users",
    create_user_handler,
    user_validator
);

Error Responses

When validation fails, the framework returns a 422 Unprocessable Entity response. The body contains the field-level error map.

json
{
  "name": ["The name field is required."],
  "email": ["The email field is required."]
}

Each field maps to an array of error messages, allowing multiple validation failures per field.