clawspec_core/_tutorial/chapter_1.rs
1//! # Chapter 1: Getting Started
2//!
3//! In this chapter, you'll learn how to create an API client and make your first request.
4//!
5//! ## Creating the Client
6//!
7//! The [`ApiClient`][crate::ApiClient] is your main entry point for making requests.
8//! Use the builder pattern to configure it:
9//!
10//! ```rust,no_run
11//! use clawspec_core::ApiClient;
12//!
13//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
14//! // Minimal client (connects to localhost:80)
15//! let client = ApiClient::builder().build()?;
16//!
17//! // Client with custom host
18//! let client = ApiClient::builder()
19//! .with_host("api.example.com")
20//! .build()?;
21//!
22//! // Client with host and port
23//! let client = ApiClient::builder()
24//! .with_host("api.example.com")
25//! .with_port(8080)
26//! .build()?;
27//!
28//! // Client with base path (all requests will be prefixed)
29//! let client = ApiClient::builder()
30//! .with_host("api.example.com")
31//! .with_base_path("/api/v1")?
32//! .build()?;
33//! # Ok(())
34//! # }
35//! ```
36//!
37//! ## Your First GET Request
38//!
39//! Let's make a simple GET request. You'll need a response type that implements
40//! [`Deserialize`][serde::Deserialize] and [`ToSchema`][utoipa::ToSchema]:
41//!
42//! ```rust,no_run
43//! use clawspec_core::ApiClient;
44//! use serde::Deserialize;
45//! use utoipa::ToSchema;
46//!
47//! #[derive(Deserialize, ToSchema)]
48//! struct User {
49//! id: u64,
50//! name: String,
51//! email: String,
52//! }
53//!
54//! # #[tokio::main]
55//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
56//! let mut client = ApiClient::builder()
57//! .with_host("api.example.com")
58//! .build()?;
59//!
60//! // Make a GET request
61//! let user: User = client
62//! .get("/users/123")? // Create the request
63//! .await? // Send it (using IntoFuture)
64//! .as_json() // Parse response as JSON
65//! .await?;
66//!
67//! println!("Got user: {} ({})", user.name, user.email);
68//! # Ok(())
69//! # }
70//! ```
71//!
72//! ## Understanding the Flow
73//!
74//! Let's break down what happens:
75//!
76//! 1. **`client.get("/users/123")?`** - Creates an [`ApiCall`][crate::ApiCall] builder
77//! 2. **`.await?`** - Sends the request (via [`IntoFuture`])
78//! 3. **`.as_json().await?`** - Parses the response body as JSON
79//!
80//! The schema for `User` is automatically captured when you call `.as_json()`.
81//!
82//! ## Generating the OpenAPI Spec
83//!
84//! After making requests, you can generate the OpenAPI specification:
85//!
86//! ```rust,no_run
87//! # use clawspec_core::ApiClient;
88//! # #[tokio::main]
89//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
90//! let mut client = ApiClient::builder().build()?;
91//!
92//! // ... make some requests ...
93//!
94//! // Get the collected OpenAPI spec
95//! let openapi = client.collected_openapi().await;
96//!
97//! // Output as YAML
98//! println!("{}", openapi.to_yaml()?);
99//!
100//! // Or as JSON
101//! println!("{}", openapi.to_pretty_json()?);
102//! # Ok(())
103//! # }
104//! ```
105//!
106//! ## Response Without Parsing
107//!
108//! Sometimes you don't need to parse the response body:
109//!
110//! ```rust,no_run
111//! # use clawspec_core::ApiClient;
112//! # #[tokio::main]
113//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
114//! # let mut client = ApiClient::builder().build()?;
115//! // Get raw response details
116//! let raw = client.get("/health")?.await?.as_raw().await?;
117//! println!("Status: {}", raw.status_code());
118//! println!("Body: {:?}", raw.text());
119//!
120//! // Or just consume the response without reading the body
121//! client.get("/ping")?.await?.as_empty().await?;
122//! # Ok(())
123//! # }
124//! ```
125//!
126//! ## Key Points
127//!
128//! - Use [`ApiClient::builder()`][crate::ApiClient::builder] to create clients
129//! - Response types need `#[derive(Deserialize, ToSchema)]`
130//! - Call `.as_json()` to parse responses and capture schemas
131//! - Use `collected_openapi()` to get the generated spec
132//!
133//! Next: [Chapter 2: Request Building][super::chapter_2] - Learn about POST requests and parameters.