Skip to content

Commit 6a6e95b

Browse files
committed
Support form
1 parent 3fac954 commit 6a6e95b

2 files changed

Lines changed: 27 additions & 3 deletions

File tree

README.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,13 +158,16 @@ pub struct CreateUserRequest {
158158
| `Path<T>` | Path parameters |
159159
| `Query<T>` | Query parameters |
160160
| `Json<T>` | Request body (application/json) |
161-
| `Form<T>` | Request body (form-urlencoded) |
162-
| `TypedMultipart<T>` | Request body (multipart/form-data) |
161+
| `Form<T>` | Request body (application/x-www-form-urlencoded) |
162+
| `TypedMultipart<T>` | Request body (multipart/form-data) — typed with schema |
163+
| `Multipart` | Request body (multipart/form-data) — untyped, generic object |
163164
| `TypedHeader<T>` | Header parameters |
164165
| `State<T>` | Ignored (internal) |
165166

166167
### Multipart Form Data
167168

169+
#### Typed Multipart (Recommended)
170+
168171
Upload files using `TypedMultipart` from [`axum_typed_multipart`](https://crates.io/crates/axum_typed_multipart):
169172

170173
```rust
@@ -188,6 +191,26 @@ Vespera automatically generates `multipart/form-data` content type in OpenAPI, a
188191

189192
> **Note:** `axum` must be a direct dependency of your project (not just via vespera) because `TryFromMultipart` internally references `axum::extract::multipart::Multipart`.
190193
194+
#### Raw Multipart (Untyped)
195+
196+
For dynamic multipart handling where the fields aren't known at compile time, use axum's built-in `Multipart` extractor:
197+
198+
```rust
199+
use axum::extract::Multipart;
200+
201+
#[vespera::route(post, tags = ["uploads"])]
202+
pub async fn upload(mut multipart: Multipart) -> Json<UploadResponse> {
203+
while let Some(field) = multipart.next_field().await.unwrap() {
204+
let name = field.name().unwrap_or("unknown").to_string();
205+
let data = field.bytes().await.unwrap();
206+
// Process each field dynamically...
207+
}
208+
Json(UploadResponse { success: true })
209+
}
210+
```
211+
212+
This generates a `multipart/form-data` request body with a generic `{ "type": "object" }` schema in OpenAPI, since the fields are not statically known.
213+
191214
### Error Handling
192215

193216
```rust

SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ pub struct User { id: u32, name: String }
5353
| `Query<T>` | query parameters | Struct fields become params |
5454
| `Json<T>` | requestBody | application/json |
5555
| `Form<T>` | requestBody | application/x-www-form-urlencoded |
56-
| `TypedMultipart<T>` | requestBody | multipart/form-data (file uploads) |
56+
| `TypedMultipart<T>` | requestBody | multipart/form-data — typed with schema |
57+
| `Multipart` | requestBody | multipart/form-data — untyped, generic object |
5758
| `State<T>` | **ignored** | Internal, not API |
5859
| `Extension<T>` | **ignored** | Internal, not API |
5960
| `TypedHeader<T>` | header parameter | |

0 commit comments

Comments
 (0)