Skip to main content

Crate roas_http_validator

Crate roas_http_validator 

Source
Expand description

Validates HTTP requests against an OpenAPI description.

roas parses a description and checks that the description is well formed. This checks that a request is what the description says it should be: the path is one the description names, the method is one that path offers, every required parameter arrived, each one is the type its Schema Object declares, and the body is what the Request Body Object describes.

use roas_http_validator::{RequestView, Validator};

let validator = Validator::new(spec);

let request = RequestView::new("GET", "/pets").with_query("limit=1000");
let report = validator.validate(&request)?;

assert!(!report.is_valid());
assert_eq!(
    report.errors[0].to_string(),
    "query parameter \"limit\": 1000 is above maximum 100",
);

§Examples

The repository carries three runnable ones: validate for the shape of the whole crate, axum_layer for the same thing as middleware (and for what buffering a body actually looks like), and client_check for asking whether a call you are about to make matches the description.

§Which request type

None of them, and all of them. Rust has no single HTTP request type to validate: http::Request comes closest, but it is generic over a body that is usually a stream, and it is version-split — actix-web 4 is on http 0.2 while hyper 1, axum 0.8 and reqwest are on 1.x, so their HeaderMaps are different types. Taking either one would shut out half the ecosystem.

So this crate takes RequestView, the small set of things an OpenAPI description actually talks about, and each framework gets a ToRequestView impl behind its own feature:

FeatureCovers
httphttp::Request, http::request::Parts — and so axum, warp, tonic, hyper
actix-webactix_web::HttpRequest
poempoem::Request
salvosalvo_core::http::Request
rocketrocket::Request
reqwestreqwest::Request and its blocking twin — the client’s side, for checking an outgoing call

The body is not part of that conversion. A framework body is a stream, and validating one means buffering it — how much, and whether at all, is the caller’s decision, so the adapters convert the head and RequestView::with_body takes the bytes. The one exception is reqwest, where a non-streaming body is already bytes in memory and there is nothing to buffer.

§Versions

The interpreter is v3.2. Enable v3_1, v3_0 or v2 to accept a description written to an older version: it is upconverted through roas’s own migrations first, so there is one interpreter rather than four.

Numbers are compared as the decimals they were written as, on both sides. The one limit is the format a description is parsed from: JSON is exact throughout, while YAML reads scalars through an f64 before serde_json is involved, so a fractional bound carrying more precision than a double is already rounded when it arrives. Every integer survives either way.

§Media types it does not read itself

JSON, application/x-www-form-urlencoded and text/* are built in. Anything else — multipart/form-data, XML — is reported rather than guessed at, and Options::decoder is the way in: the bytes become a value and the Schema Object judges it like any other.

Those two are a hook rather than more built-ins on purpose. Multipart would mean owning a boundary parser and buffering file uploads, which is exactly where this crate leaves buffering to the caller. XML has no specified mapping onto a schema instance at all — OpenAPI’s XML Object is serialization metadata for code generators — so any translation is a choice, and taking the caller’s beats inventing one.

§What it does not check yet

Response validation and security requirements.

Everything a check could not judge is reported rather than passed over, so a request never looks valid because nothing looked at it: ErrorKind::Unsupported for what is not implemented, ErrorKind::Unchecked for a description this crate can read but cannot apply faithfully. ValidationReport::unchecked separates both from what the request definitely got wrong.

Structs§

Options
What to check, and where the description’s paths start.
RequestView
One HTTP request, as much of it as an OpenAPI description describes.
ValidationError
One thing wrong with the request.
ValidationReport
The verdict on one request that the description does describe.
Validator
One OpenAPI description, ready to judge requests against.

Enums§

ErrorKind
What was wrong with one parameter or with the body.
Location
Where in the request an error was found.
RoutingError
The description does not describe this request at all.

Traits§

ToRequestView
A framework’s own request type, seen as a RequestView.

Type Aliases§

Decoder
Turns a body of one media type into the value its schema judges.