ferro_inertia/request.rs
1//! Request trait for framework-agnostic Inertia header extraction.
2
3/// Trait for extracting Inertia-specific data from HTTP requests.
4///
5/// Implement this trait for your framework's request type to enable
6/// Inertia.js integration.
7///
8/// # Example
9///
10/// ```rust,ignore
11/// use ferro_inertia::InertiaRequest;
12///
13/// impl InertiaRequest for axum::extract::Request {
14/// fn inertia_header(&self, name: &str) -> Option<&str> {
15/// self.headers()
16/// .get(name)
17/// .and_then(|v| v.to_str().ok())
18/// }
19///
20/// fn path(&self) -> &str {
21/// self.uri().path()
22/// }
23/// }
24/// ```
25pub trait InertiaRequest {
26 /// Get a header value by name.
27 ///
28 /// Used to extract Inertia-specific headers like `X-Inertia`,
29 /// `X-Inertia-Version`, and `X-Inertia-Partial-Data`.
30 fn inertia_header(&self, name: &str) -> Option<&str>;
31
32 /// Get the request path (URL path component).
33 fn path(&self) -> &str;
34
35 /// Check if this is an Inertia XHR request.
36 ///
37 /// Returns `true` if the `X-Inertia` header is present and set to "true".
38 fn is_inertia(&self) -> bool {
39 self.inertia_header("X-Inertia")
40 .map(|v| v == "true")
41 .unwrap_or(false)
42 }
43
44 /// Get the Inertia asset version from the request.
45 ///
46 /// Returns the value of the `X-Inertia-Version` header if present.
47 fn inertia_version(&self) -> Option<&str> {
48 self.inertia_header("X-Inertia-Version")
49 }
50
51 /// Get the partial reload data keys.
52 ///
53 /// Returns a list of prop keys requested for partial reload via
54 /// the `X-Inertia-Partial-Data` header.
55 fn inertia_partial_data(&self) -> Option<Vec<&str>> {
56 self.inertia_header("X-Inertia-Partial-Data")
57 .map(|v| v.split(',').map(str::trim).collect())
58 }
59
60 /// Get the component name for partial reload.
61 ///
62 /// Returns the value of the `X-Inertia-Partial-Component` header.
63 fn inertia_partial_component(&self) -> Option<&str> {
64 self.inertia_header("X-Inertia-Partial-Component")
65 }
66
67 /// Check if the request accepts JSON responses.
68 ///
69 /// Returns `true` if the `Accept` header contains `application/json`.
70 fn accepts_json(&self) -> bool {
71 self.inertia_header("Accept")
72 .map(|v| v.contains("application/json"))
73 .unwrap_or(false)
74 }
75}