Clawspec Core
Generate OpenAPI specifications from your HTTP client test code.
This crate provides two main ways to generate OpenAPI documentation:
- [
ApiClient] - Direct HTTP client for fine-grained control
TestClient - Test server integration with automatic lifecycle management
Quick Start
Using ApiClient directly
use clawspec_core::ApiClient;
# use serde::Deserialize;
# use utoipa::ToSchema;
# #[derive(Deserialize, ToSchema)]
# struct User { id: u32, name: String }
# #[tokio::main]
# async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = ApiClient::builder()
.with_host("api.example.com")
.build()?;
let user: User = client
.get("/users/123")?
.await? .as_json() .await?;
let spec = client.collected_openapi().await;
# Ok(())
# }
Using TestClient with a test server
For a complete working example, see the axum example.
use clawspec_core::test_client::{TestClient, TestServer};
use std::net::TcpListener;
# #[derive(Debug)]
# struct MyServer;
# impl TestServer for MyServer {
# type Error = std::io::Error;
# async fn launch(&self, listener: TcpListener) -> Result<(), Self::Error> {
# Ok(())
# }
# }
#[tokio::test]
async fn test_api() -> Result<(), Box<dyn std::error::Error>> {
let mut client = TestClient::start(MyServer).await?;
let response = client.get("/users")?.await?.as_json::<serde_json::Value>().await?;
client.write_openapi("api.yml").await?;
Ok(())
}
Working with Parameters
use clawspec_core::{ApiClient, CallPath, CallQuery, CallHeaders, ParamValue};
# async fn example(client: &mut ApiClient) -> Result<(), Box<dyn std::error::Error>> {
let mut path = CallPath::from("/users/{id}");
path.add_param("id", ParamValue::new(123));
let query = CallQuery::new()
.add_param("page", ParamValue::new(1))
.add_param("limit", ParamValue::new(10));
let headers = CallHeaders::new()
.add_header("Authorization", "Bearer token");
let response = client
.get(path)?
.with_query(query)
.with_headers(headers)
.await?; # Ok(())
# }
Status Code Validation
By default, requests expect status codes in the range 200-499 (inclusive of 200, exclusive of 500).
You can customize this behavior:
use clawspec_core::{ApiClient, expected_status_codes};
# async fn example(client: &mut ApiClient) -> Result<(), Box<dyn std::error::Error>> {
client.post("/users")?
.with_expected_status_codes(expected_status_codes!(201, 202))
.await?;
client.get("/health")?
.with_expected_status_codes(expected_status_codes!(200-299))
.await?;
# Ok(())
# }
Schema Registration
use clawspec_core::{ApiClient, register_schemas};
# use serde::Deserialize;
# use utoipa::ToSchema;
#[derive(Deserialize, ToSchema)]
struct CreateUser { name: String, email: String }
#[derive(Deserialize, ToSchema)]
struct ErrorResponse { code: String, message: String }
# fn example(client: &mut ApiClient) {
register_schemas!(client, CreateUser, ErrorResponse);
# }
Error Handling
The library provides two main error types:
- [
ApiClientError] - HTTP client errors (network, parsing, validation)
TestAppError - Test server lifecycle errors
See Also
- [
ApiClient] - HTTP client with OpenAPI collection
- [
ApiCall] - Request builder with parameter support
- [
test_client] - Test server integration module
- [
ExpectedStatusCodes] - Status code validation
Re-exports
All commonly used types are re-exported from the crate root for convenience.