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:
| Feature | Covers |
|---|---|
http | http::Request, http::request::Parts — and so axum, warp, tonic, hyper |
actix-web | actix_web::HttpRequest |
poem | poem::Request |
salvo | salvo_core::http::Request |
rocket | rocket::Request |
reqwest | reqwest::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.
- Request
View - One HTTP request, as much of it as an OpenAPI description describes.
- Validation
Error - One thing wrong with the request.
- Validation
Report - The verdict on one request that the description does describe.
- Validator
- One OpenAPI description, ready to judge requests against.
Enums§
- Error
Kind - What was wrong with one parameter or with the body.
- Location
- Where in the request an error was found.
- Routing
Error - The description does not describe this request at all.
Traits§
- ToRequest
View - 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.