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.
§What it does not do yet
Response validation, security requirements, multipart/form-data
bodies, and XML — and exact decimal arithmetic, which would need
serde_json’s arbitrary_precision: numbers are compared as the
IEEE-754 doubles they arrive as, and anything that would over-claim
on top of one is reported rather than assumed. Anything a check
could not judge is reported — split out by
ValidationReport::unchecked from what the request definitely got
wrong —
ErrorKind::Unsupported for what is not implemented yet,
ErrorKind::Unchecked for a description this crate can read but
cannot apply faithfully — rather than passed over, so a request
never looks valid because nothing looked at it.
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.