### Define HTTP Methods (GET, POST, PUT, DELETE) in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Demonstrates how to define routes for different HTTP methods (GET, POST, PUT, DELETE) using the Skyzen routing capabilities. It includes examples for listing, creating, updating, and deleting posts, showcasing parameter handling and JSON serialization/deserialization. Dependencies include `skyzen` and `serde`. ```rust use skyzen::{ routing::{CreateRouteNode, Params, Route, Router}, utils::Json, Result, }; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] struct Post { id: u64, title: String, } async fn list_posts() -> Json> { Json(vec![Post { id: 1, title: "First Post".into() }]) } async fn create_post(Json(post): Json) -> Json { Json(post) } async fn update_post(params: Params, Json(post): Json) -> Result> { let id = params.get("id")?; Ok(Json(Post { id: id.parse().unwrap_or(0), title: post.title })) } async fn delete_post(params: Params) -> Result { let id = params.get("id")?; Ok(format!("Deleted post {id}")) } #[skyzen::main] fn main() -> Router { Route::new(( "/posts".get(list_posts), "/posts".post(create_post), "/posts/{id}".put(update_post), "/posts/{id}".delete(delete_post), )) .build() } // GET /posts -> [{"id":1,"title":"First Post"}] // POST /posts {"id":2,"title":"New"} -> {"id":2,"title":"New"} // PUT /posts/2 {"title":"Updated"} -> {"id":2,"title":"Updated"} // DELETE /posts/2 -> "Deleted post 2" ``` -------------------------------- ### OpenAPI Documentation with Skyzen Source: https://github.com/zen-rs/skyzen/blob/main/examples/README.md Showcases the `#[skyzen::openapi]` macro for generating OpenAPI documentation directly from Skyzen handlers. It demonstrates building a Router, invoking `.openapi()`, and inspecting the collected operations. Schemas and doc comments are printed in debug mode, while release builds disable instrumentation. ```rust use skyzen::extract::Json; use skyzen::response::Json; use skyzen::routing::Router; use skyzen::Skyzen; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize)] struct User { username: String, } #[skyzen::openapi] async fn create_user(user: Json) -> Json { user } fn main() { let app = Skyzen::new().route("/user", skyzen::routing::post_with(create_user)); // To run this example: // cargo run --example openapi // In debug mode, this will print OpenAPI schemas and doc comments. // In release mode, OpenAPI instrumentation is disabled and a message is logged. Skyzen::run(app).await.unwrap(); } ``` -------------------------------- ### Skyzen Worker for WASM and Native Compilation Source: https://github.com/zen-rs/skyzen/blob/main/examples/README.md Demonstrates a single Skyzen entry point that compiles to both native binaries and WinterCG fetch handlers, suitable for platforms like Cloudflare Workers. It supports simple text routes that can be tested with curl or preview environments. The example includes instructions for running natively and building for WASM. ```rust use skyzen::http::StatusCode; use skyzen::routing::Router; use skyzen::Skyzen; async fn text_handler() -> &'static str { "Hello from Skyzen Worker!" } #[skyzen::main] async fn worker() { let app = Skyzen::new().route("/", skyzen::routing::get(text_handler)); // To run natively (for development): // cargo run --example worker // To build for Cloudflare Workers: // 1. Add wasm32 target: // rustup target add wasm32-unknown-unknown // 2. Build for release: // cargo build --example worker --target wasm32-unknown-unknown --release // 3. Bind WASM with wasm-bindgen: // wasm-bindgen --target web target/wasm32-unknown-unknown/release/examples/worker.wasm --out-dir worker-dist // 4. Deploy using wrangler: // wrangler publish worker-dist/worker.js (after creating worker.js to import and forward fetch) Skyzen::run(app).await.unwrap(); } ``` -------------------------------- ### Basic HTTP Server with Routing in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Demonstrates how to create a simple HTTP server with multiple routes using the Skyzen framework. It defines two routes: one for the root path and another for a health check. This example requires the `skyzen` crate and uses the `skyzen::main` attribute. ```rust use skyzen::routing::{CreateRouteNode, Route, Router}; #[skyzen::main] fn main() -> Router { Route::new(( "/".at(|| async { "Hello, World!" }), "/health".at(|| async { "OK" }), )) .build() } // Run with: cargo run // Visit: http://127.0.0.1:8787 ``` -------------------------------- ### Native Router with Skyzen Source: https://github.com/zen-rs/skyzen/blob/main/examples/README.md Builds a Skyzen Router with nested routes, utilizing Query and Params extractors for parsing query strings and path parameters. It returns strongly typed JSON responses using the Json responder. This example runs locally and can be configured with CLI flags for port settings. ```rust use skyzen::extract::{Params, Query}; use skyzen::http::StatusCode; use skyzen::response::Json; use skyzen::routing::Router; use skyzen::Skyzen; use serde::Serialize; #[derive(Serialize)] struct HelloMessage { message: String, } async fn hello_handler() -> Json { Json(HelloMessage { message: "Hello, Skyzen!".to_string() }) } async fn hello_name_handler(Params(name): Params) -> Json { Json(HelloMessage { message: format!("Hello, {}!", name) }) } async fn hello_query_handler( query: Query<( Option, Option, )>, ) -> Result, StatusCode> { let (name, excited) = query.0; let message = match (name, excited) { (Some(name), Some(true)) => format!("Hello, {}! You are excited!", name), (Some(name), _) => format!("Hello, {}!", name), (None, Some(true)) => "You are excited!".to_string(), (None, _) => "Hello, Skyzen!".to_string(), }; Ok(Json(HelloMessage { message })) } async fn healthz_handler() -> StatusCode { StatusCode::OK } fn main() { let app = Skyzen::new() .nest( "/hello", Router::new() .get("/", hello_handler) .get("/:name", hello_name_handler) .get_with("/", hello_query_handler), ) .route("/healthz", skyzen::routing::get(healthz_handler)); // To run this example: // cargo run --example native -- --port 3000 // Then visit http://127.0.0.1:3000/hello?name=Skyzen&excited=true // Or http://127.0.0.1:3000/hello/World // Or http://127.0.0.1:3000/hello // Or http://127.0.0.1:3000/healthz Skyzen::run(app).await.unwrap(); } ``` -------------------------------- ### Create a Simple Skyzen Application Source: https://github.com/zen-rs/skyzen/blob/main/README.md This is the most basic Skyzen application. It defines two routes: one for the root path ('/') that returns 'Hello, World!' and another for '/health' that returns 'OK'. The `#[skyzen::main]` macro handles the server setup, logging, and graceful shutdown. The application listens on `http://127.0.0.1:8787` by default. ```rust use skyzen::routing::{CreateRouteNode, Route, Router}; #[skyzen::main] fn main() -> Router { Route::new(( "/".at(|| async { "Hello, World!" }), "/health".at(|| async { "OK" }), )) .build() } ``` -------------------------------- ### Project: /zen-rs/skyzen - HTTP Methods Source: https://context7.com/zen-rs/skyzen/llms.txt This section covers defining routes with different HTTP methods (GET, POST, PUT, DELETE) for managing posts. ```APIDOC ## GET /posts ### Description Retrieves a list of all posts. ### Method GET ### Endpoint /posts ### Parameters None ### Request Example None ### Response #### Success Response (200) - **posts** (array) - A list of post objects. - **id** (u64) - The unique identifier of the post. - **title** (string) - The title of the post. #### Response Example ```json [ { "id": 1, "title": "First Post" } ] ``` ## POST /posts ### Description Creates a new post. ### Method POST ### Endpoint /posts ### Parameters None #### Request Body - **post** (object) - The post object to create. - **id** (u64) - The unique identifier of the post. - **title** (string) - The title of the post. ### Request Example ```json { "id": 2, "title": "New" } ``` ### Response #### Success Response (200) - **post** (object) - The newly created post object. - **id** (u64) - The unique identifier of the post. - **title** (string) - The title of the post. #### Response Example ```json { "id": 2, "title": "New" } ``` ## PUT /posts/{id} ### Description Updates an existing post identified by its ID. ### Method PUT ### Endpoint /posts/{id} #### Path Parameters - **id** (string) - Required - The ID of the post to update. #### Request Body - **post** (object) - The updated post object. - **title** (string) - The new title for the post. ### Request Example ```json { "title": "Updated" } ``` ### Response #### Success Response (200) - **post** (object) - The updated post object. - **id** (u64) - The unique identifier of the post. - **title** (string) - The updated title of the post. #### Response Example ```json { "id": 2, "title": "Updated" } ``` ## DELETE /posts/{id} ### Description Deletes a post identified by its ID. ### Method DELETE ### Endpoint /posts/{id} #### Path Parameters - **id** (string) - Required - The ID of the post to delete. ### Request Example None ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating the post was deleted. #### Response Example ``` "Deleted post 2" ``` ``` -------------------------------- ### Path Parameters Extraction in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Illustrates how to extract dynamic path segments from URLs using Skyzen's `Params` extractor. This example defines routes with placeholders like `{name}` and `{id}` which are then accessed via the `params.get()` method. It requires `serde` for serialization and deserialization, and `skyzen` for routing and utilities. ```rust use serde::{Deserialize, Serialize}; use skyzen::{ routing::{CreateRouteNode, Params, Route, Router}, utils::Json, Result, }; #[derive(Debug, Serialize)] struct Greeting { message: String, } async fn greet(params: Params) -> Result> { let name = params.get("name")?; Ok(Json(Greeting { message: format!("Hello, {name}!"), })) } #[skyzen::main] fn main() -> Router { Route::new(( "/hello/{name}".at(greet), "/users/{id}/posts/{post_id}".at(|params: Params| async move { let user_id = params.get("id")?; let post_id = params.get("post_id")?; Ok(format!("User {user_id}, Post {post_id}")) }), )) .build() } // GET /hello/Skyzen -> {"message": "Hello, Skyzen!"} // GET /users/42/posts/123 -> "User 42, Post 123" ``` -------------------------------- ### Using the `#[skyzen::main]` Macro Source: https://github.com/zen-rs/skyzen/blob/main/README.md The `#[skyzen::main]` macro simplifies the setup of Skyzen HTTP servers. It automatically configures logging (respecting `RUST_LOG`), enables graceful shutdown on `Ctrl+C`, allows CLI overrides for host and port, and sets up the Tokio and Hyper runtime. The macro can also be configured to disable the default logger. ```rust #[skyzen::main] fn main() -> Router { router() } ``` ```rust #[skyzen::main(default_logger = false)] async fn main() -> Router { tracing_subscriber::fmt().init(); router() } ``` -------------------------------- ### Skyzen Routing with Parameters and Methods Source: https://github.com/zen-rs/skyzen/blob/main/README.md Demonstrates advanced routing capabilities in Skyzen. This includes defining routes with path parameters (e.g., `/users/{id}`), handling different HTTP methods (GET, POST, PUT, DELETE) for a specific path (e.g., `/posts`), and using a placeholder for handler functions like `list_posts`. ```rust use skyzen::routing::{CreateRouteNode, Route, Router}; fn router() -> Router { Route::new(( // Simple handlers "/".at(|| async { "Home" }), // Path parameters "/users/{id}".at(|params: Params| async move { let id = params.get("id")?; Ok(format!("User: {id}")) }), // HTTP methods "/posts".get(list_posts), "/posts".post(create_post), "/posts/{id}".put(update_post), "/posts/{id}".delete(delete_post), )) .build() } ``` -------------------------------- ### Comprehensive REST API Example with Skyzen Source: https://context7.com/zen-rs/skyzen/llms.txt This Rust code demonstrates a full-featured CRUD API for managing articles. It includes state management using `Arc>`, custom error handling with `#[skyzen::error]`, and automatic OpenAPI documentation generation via `#[skyzen::openapi]`. The API supports listing, creating, and retrieving articles, with filtering capabilities. ```rust use std::{ collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicUsize, Ordering}}, }; use serde::{Deserialize, Serialize}; use skyzen::{ extract::Query, routing::{CreateRouteNode, Params, Route, Router}, utils::{Json, State}, StatusCode, ToSchema, }; type SharedStore = Arc; #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] struct Article { id: String, title: String, body: String, tags: Vec, } #[derive(Debug, Deserialize, ToSchema)] struct ArticleDraft { title: String, body: String, tags: Vec, } #[derive(Debug, Deserialize, ToSchema)] struct ArticleFilter { tags: Option>, search: Option, } #[skyzen::error] enum ApiError { #[error("article not found", status = StatusCode::NOT_FOUND)] NotFound, #[error("title already exists", status = StatusCode::CONFLICT)] DuplicateTitle, } #[derive(Default)] struct ArticleStore { next_id: AtomicUsize, items: Mutex>, } impl ArticleStore { fn insert(&self, draft: ArticleDraft) -> Result { let id = self.next_id.fetch_add(1, Ordering::Relaxed) + 1; let article = Article { id: format!("art-{id}"), title: draft.title, body: draft.body, tags: draft.tags, }; self.items.lock().unwrap().insert(article.id.clone(), article.clone()); Ok(article) } fn get(&self, id: &str) -> Option
{ self.items.lock().unwrap().get(id).cloned() } fn list(&self, filter: &ArticleFilter) -> Vec
{ self.items.lock().unwrap().values().cloned().collect() } } #[skyzen::openapi] async fn list_articles( Query(filter): Query, State(store): State, ) -> skyzen::Result>> { Ok(Json(store.list(&filter))) } #[skyzen::openapi] async fn create_article( State(store): State, Json(draft): Json, ) -> Result, ApiError> { Ok(Json(store.insert(draft)?)) } #[skyzen::openapi] async fn get_article( params: Params, State(store): State, ) -> Result, ApiError> { let id = params.get("id").map_err(|_| ApiError::NotFound)?; store.get(id).map(Json).ok_or(ApiError::NotFound) } #[skyzen::main] fn main() -> Router { let store = State(Arc::new(ArticleStore::default())); Route::new(( "/articles".get(list_articles).post(create_article), "/articles/{id}".at(get_article), )) .middleware(store) .enable_api_doc() .build() } // GET /articles?tags=rust,web -> [{"id":"art-1",...}] // POST /articles {"title":"New","body":"...","tags":["rust"]} // GET /articles/art-1 -> {"id":"art-1",...} // GET /api-docs -> Interactive API documentation ``` -------------------------------- ### Query Parameter Extraction in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Shows how to parse URL query strings into typed structures using Skyzen's `Query` extractor. The `SearchQuery` struct is automatically populated from the URL parameters. This example requires `serde` for deserialization and `skyzen` for extractors and routing. ```rust use serde::{Deserialize, Serialize}; use skyzen::{ extract::Query, routing::{CreateRouteNode, Route, Router}, utils::Json, }; #[derive(Debug, Deserialize)] struct SearchQuery { q: String, page: Option, limit: Option, } #[derive(Debug, Serialize)] struct SearchResult { query: String, page: u32, limit: u32, } async fn search(Query(query): Query) -> Json { Json(SearchResult { query: query.q, page: query.page.unwrap_or(1), limit: query.limit.unwrap_or(10), }) } #[skyzen::main] fn main() -> Router { Route::new(("/search".at(search),)) .build() } // GET /search?q=rust&page=2&limit=20 // -> {"query":"rust","page":2,"limit":20} ``` -------------------------------- ### Share Application State with Middleware in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Shows how to implement middleware in Skyzen to share application state across handlers. This example uses `Arc` to make configuration accessible to multiple endpoints, demonstrating state injection via `State` extractor. Dependencies include `skyzen`, `std::sync::Arc`, and `serde`. ```rust use std::sync::Arc; use skyzen::{ routing::{CreateRouteNode, Route, Router}, utils::{Json, State}, Result, }; use serde::Serialize; #[derive(Clone, Debug)] struct AppConfig { api_key: String, max_requests: usize, } #[derive(Serialize)] struct ConfigResponse { max_requests: usize, } async fn get_config(State(config): State>) -> Json { Json(ConfigResponse { max_requests: config.max_requests, }) } async fn protected_endpoint(State(config): State>) -> String { format!("API Key: {}", config.api_key) } #[skyzen::main] fn main() -> Router { let config = State(Arc::new(AppConfig { api_key: "secret123".to_string(), max_requests: 1000, })); Route::new(( "/config".at(get_config), "/protected".at(protected_endpoint), )) .middleware(config) .build() } // GET /config -> {"max_requests":1000} // GET /protected -> "API Key: secret123" ``` -------------------------------- ### Add Skyzen Dependency Source: https://github.com/zen-rs/skyzen/blob/main/README.md To use Skyzen in your Rust project, add the `skyzen` crate to your `Cargo.toml` file under the `[dependencies]` section. Specify the desired version, for example, `0.1`. ```toml [dependencies] skyzen = "0.1" ``` -------------------------------- ### WebSocket Server with JSON Messages in SkyZen Source: https://context7.com/zen-rs/skyzen/llms.txt This example demonstrates a WebSocket server in Rust using SkyZen that handles structured JSON messages. It defines a `ChatMessage` struct for serialization and deserialization. The server receives JSON messages, processes them, and sends back an echoed JSON response. It uses `recv_json` for receiving and `send` for sending JSON. ```rust use futures_util::StreamExt; use serde::{Deserialize, Serialize}; use skyzen::{ routing::{CreateRouteNode, Route, Router}, websocket::WebSocketUpgrade, Responder, }; #[derive(Serialize, Deserialize, Debug)] struct ChatMessage { user: String, content: String, } async fn websocket_json(upgrade: WebSocketUpgrade) -> impl Responder { upgrade.on_upgrade(|mut socket| async move { while let Some(Ok(msg)) = socket.recv_json::().await { println!("Received from {}: {}", msg.user, msg.content); let response = ChatMessage { user: "server".to_string(), content: format!("Echo: {}", msg.content), }; let _ = socket.send(&response).await; } }) } #[skyzen::main] fn main() -> Router { Route::new(("/ws/json".ws(websocket_json),)) .build() } // Send JSON: {"user":"alice","content":"hello"} // Receive: {"user":"server","content":"Echo: hello"} ``` -------------------------------- ### Project: /zen-rs/skyzen - Middleware with State Management Source: https://context7.com/zen-rs/skyzen/llms.txt Illustrates sharing application state across handlers using middleware, such as API configuration. ```APIDOC ## GET /config ### Description Retrieves the application configuration, specifically the maximum number of requests allowed. ### Method GET ### Endpoint /config ### Parameters None ### Request Example None ### Response #### Success Response (200) - **config** (object) - The application configuration. - **max_requests** (usize) - The maximum number of requests allowed. #### Response Example ```json { "max_requests": 1000 } ``` ## GET /protected ### Description Accesses a protected endpoint that requires an API key, demonstrating state management. ### Method GET ### Endpoint /protected ### Parameters None ### Request Example None ### Response #### Success Response (200) - **message** (string) - A string containing the API key. #### Response Example ``` "API Key: secret123" ``` ``` -------------------------------- ### Project: /zen-rs/skyzen - Nested Routes Source: https://context7.com/zen-rs/skyzen/llms.txt Demonstrates organizing routes hierarchically with shared prefixes for user and post-related endpoints. ```APIDOC ## GET /api/v1/users/{id} ### Description Retrieves information about a specific user. ### Method GET ### Endpoint /api/v1/users/{id} #### Path Parameters - **id** (string) - Required - The ID of the user. ### Request Example None ### Response #### Success Response (200) - **message** (string) - A string indicating the user found. #### Response Example ``` "User 123" ``` ## GET /api/v1/users/{id}/posts ### Description Retrieves a list of posts for a specific user. ### Method GET ### Endpoint /api/v1/users/{id}/posts #### Path Parameters - **id** (string) - Required - The ID of the user whose posts to retrieve. ### Request Example None ### Response #### Success Response (200) - **message** (string) - A string indicating the posts found for the user. #### Response Example ``` "Posts for user 123" ``` ## GET /api/v1/users/{id}/posts/{post_id} ### Description Retrieves a specific post for a specific user. ### Method GET ### Endpoint /api/v1/users/{id}/posts/{post_id} #### Path Parameters - **id** (string) - Required - The ID of the user. - **post_id** (string) - Required - The ID of the post. ### Request Example None ### Response #### Success Response (200) - **message** (string) - A string indicating the user and post found. #### Response Example ``` "User 123, Post 456" ``` ``` -------------------------------- ### JSON Request and Response Handling in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Demonstrates how to accept JSON data in a request body and return JSON data in the response using Skyzen's `Json` utility. The `CreateUser` struct is deserialized from the request body, and the `User` struct is serialized to JSON for the response. This requires `serde` for serialization/deserialization and `skyzen` for routing and JSON utilities. ```rust use serde::{Deserialize, Serialize}; use skyzen::{ routing::{CreateRouteNode, Route, Router}, utils::Json, Result, }; #[derive(Debug, Deserialize)] struct CreateUser { username: String, email: String, } #[derive(Debug, Serialize)] struct User { id: u64, username: String, email: String, } async fn create_user(Json(body): Json) -> Result> { let user = User { id: 123, username: body.username, email: body.email, }; Ok(Json(user)) } #[skyzen::main] fn main() -> Router { Route::new(("/users".post(create_user),)) .build() } // POST /users // Content-Type: application/json // {"username":"alice","email":"alice@example.com"} // -> {"id":123,"username":"alice","email":"alice@example.com"} ``` -------------------------------- ### Skyzen OpenAPI Documentation Generation Source: https://github.com/zen-rs/skyzen/blob/main/README.md Skyzen supports automatic generation of OpenAPI documentation. By annotating handler functions with `#[skyzen::openapi]`, you can enable the framework to serve API documentation, typically at the `/api-docs` endpoint. This feature simplifies API documentation management for your services. ```rust #[skyzen::openapi] async fn get_user(params: Params) -> Result> { // Handler implementation } fn router() -> Router { Route::new(("/users/{id}".at(get_user),)) .enable_api_doc() // Serves docs at /api-docs .build() } ``` -------------------------------- ### WebAssembly Edge Deployment with Skyzen Source: https://context7.com/zen-rs/skyzen/llms.txt This Rust code demonstrates deploying a Skyzen router to WebAssembly edge environments such as Cloudflare Workers. It defines simple routes for health checks and greetings. The `#[skyzen::main]` macro allows the same router code to function on both native and WASM targets, enabling code reuse across different deployment environments. ```rust use skyzen::routing::{CreateRouteNode, Params, Route, Router}; use skyzen::Result; async fn health() -> &'static str { "OK" } async fn greet(params: Params) -> Result { let name = params.get("name")?; Ok(format!("Hello, {name}!")) } #[skyzen::main] fn worker() -> Router { Route::new(( "/".at(|| async { "Edge Function Running" }), "/health".at(health), "/hello/{name}".at(greet), )) .build() } #[cfg(target_arch = "wasm32")] fn main() {} // Build: cargo build --target wasm32-unknown-unknown --release // Deploy to Cloudflare Workers, Deno Deploy, or other WinterCG platforms // The same router code runs on both native and WASM targets ``` -------------------------------- ### Organize Routes Hierarchically with Nested Routes in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Illustrates how to organize routes hierarchically using nested `Route::new` structures in Skyzen. This allows for shared prefixes and logical grouping of related endpoints, such as user-specific resources. Dependencies include `skyzen`. ```rust use skyzen::{ routing::{CreateRouteNode, Params, Route, Router}, Result, }; async fn get_user(params: Params) -> Result { let id = params.get("id")?; Ok(format!("User {id}")) } async fn list_user_posts(params: Params) -> Result { let user_id = params.get("id")?; Ok(format!("Posts for user {user_id}")) } async fn get_user_post(params: Params) -> Result { let user_id = params.get("id")?; let post_id = params.get("post_id")?; Ok(format!("User {user_id}, Post {post_id}")) } #[skyzen::main] fn main() -> Router { Route::new(( "/api/v1".route(( "/users/{id}".at(get_user).route(( "/posts".at(list_user_posts), "/posts/{post_id}".at(get_user_post), )), )), )) .build() } // GET /api/v1/users/123 -> "User 123" // GET /api/v1/users/123/posts -> "Posts for user 123" // GET /api/v1/users/123/posts/456 -> "User 123, Post 456" ``` -------------------------------- ### Multipart File Upload in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Illustrates handling file uploads via multipart form data using Skyzen's `Multipart` utility. The `upload` function iterates through uploaded fields, extracts filenames and data, and returns a JSON response containing file information. ```rust use skyzen:: routing::{CreateRouteNode, Route, Router}, utils::{Json, Multipart}, Result, ; use serde::Serialize; #[derive(Serialize)] struct UploadResult { files: Vec, } #[derive(Serialize)] struct FileInfo { name: String, size: usize, } async fn upload(mut multipart: Multipart) -> Result> { let mut files = Vec::new(); while let Some(field) = multipart.next_field().await? { if let Some(filename) = field.file_name() { let data = field.bytes().await?; files.push(FileInfo { name: filename.to_string(), size: data.len(), }); } } Ok(Json(UploadResult { files })) } #[skyzen::main] fn main() -> Router { Route::new(("/upload".post(upload),)) .build() } // POST /upload // Content-Type: multipart/form-data; boundary=----WebKitFormBoundary // [multipart data with files] // -> {"files":[{"name":"file.txt","size":1024}]} ``` -------------------------------- ### Generate OpenAPI Docs with SkyZen Attribute Source: https://context7.com/zen-rs/skyzen/llms.txt This snippet demonstrates how to automatically generate OpenAPI documentation for API endpoints using the `#[skyzen::openapi]` attribute. It defines request and response schemas using Serde and SkyZen's `ToSchema` trait. The generated documentation can be accessed interactively at the `/api-docs` path. ```rust use serde::{Deserialize, Serialize}; use skyzen::{ extract::Query, routing::{CreateRouteNode, Params, Route, Router}, utils::Json, StatusCode, ToSchema, }; #[derive(Debug, Deserialize, ToSchema)] struct TaskFilter { tags: Option>, limit: Option, } #[derive(Debug, Deserialize, Serialize, ToSchema)] struct TaskDraft { title: String, priority: String, } #[derive(Debug, Serialize, ToSchema)] struct Task { id: String, title: String, priority: String, } /// Create a new task under a project #[skyzen::openapi] async fn create_task( params: Params, Query(filter): Query, Json(draft): Json, ) -> skyzen::Result> { let project_id = params.get("project_id")?; let task = Task { id: "task-123".into(), title: draft.title, priority: draft.priority, }; Ok(Json(task)) } #[skyzen::main] fn main() -> Router { Route::new(( "/projects/{project_id}/tasks".post(create_task), )) .enable_api_doc() // Serves interactive docs at /api-docs .build() } // POST /projects/proj1/tasks?limit=10 // {"title":"Fix bug","priority":"high"} // -> {"id":"task-123","title":"Fix bug","priority":"high"} // Visit /api-docs for interactive ReDoc documentation ``` -------------------------------- ### Implement WebSocket Echo Server with SkyZen Source: https://context7.com/zen-rs/skyzen/llms.txt This Rust code sets up a basic WebSocket server that echoes back any text messages it receives. It uses SkyZen's WebSocket capabilities for handling the upgrade request and managing the bidirectional communication. The server is configured to listen on the `/ws` path. It breaks the loop upon receiving a Close message. ```rust use futures_util::StreamExt; use skyzen::{ routing::{CreateRouteNode, Route, Router}, websocket::{WebSocketMessage, WebSocketUpgrade}, Responder, }; async fn websocket_echo(upgrade: WebSocketUpgrade) -> impl Responder { upgrade.on_upgrade(|mut socket| async move { while let Some(Ok(message)) = socket.next().await { match message { WebSocketMessage::Text(text) => { let _ = socket.send_text(format!("Echo: {text}")).await; } WebSocketMessage::Close => break, _ => {} } } }) } #[skyzen::main] fn main() -> Router { Route::new(("/ws".ws(websocket_echo),)) .build() } // Connect with: websocat ws://127.0.0.1:8787/ws // Send: "Hello" -> Receive: "Echo: Hello" ``` -------------------------------- ### Skyzen WebSocket Support Source: https://github.com/zen-rs/skyzen/blob/main/README.md Shows how to implement WebSocket endpoints in Skyzen. The `.ws` method is used for simple echo servers and more complex scenarios involving protocol negotiation. WebSocket support is available for both native Rust applications (using `async-tungstenite`) and WebAssembly (using `WebSocketPair`). ```rust use skyzen::routing::{CreateRouteNode, Route}; use skyzen::websocket::WebSocketUpgrade; Route::new(( // Simple echo server "/ws".ws(|mut socket| async move { while let Some(Ok(message)) = socket.next().await { if let Some(text) = message.into_text() { let _ = socket.send_text(text).await; } } }), // With protocol negotiation "/chat".at(|upgrade: WebSocketUpgrade| async move { upgrade .protocols(["chat", "superchat"]) .on_upgrade(|mut socket| async move { // Handle the connection }) }), )) ``` -------------------------------- ### SSE with Channel Pattern in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Demonstrates sending Server-Sent Events (SSE) from background tasks to SSE streams using a channel pattern. It utilizes Skyzen's responder and routing utilities. The function `sse_channel` sets up the SSE stream and a background task to send updates. ```rust use skyzen:: responder::{Sse, sse::Event}, routing::{CreateRouteNode, Route, Router}, ; use std::time::Duration; async fn sse_channel() -> Sse { let (sender, sse) = Sse::channel(); tokio::spawn(async move { for i in 0..10 { tokio::time::sleep(Duration::from_millis(500)).await; if sender.send_data(format!("Update {i}")).is_err() { break; } } }); sse } #[skyzen::main] fn main() -> Router { Route::new(("/updates".at(sse_channel),)) .build() } // curl http://127.0.0.1:8787/updates // Receives 10 messages at 500ms intervals ``` -------------------------------- ### Skyzen WASM Deployment Source: https://github.com/zen-rs/skyzen/blob/main/README.md Skyzen applications can be compiled to WebAssembly for deployment on edge platforms. The `#[skyzen::main]` macro automatically exports a WinterCG-compatible `fetch` handler when targeting WASM. This allows the application to run on platforms like Cloudflare Workers and Deno Deploy. ```sh cargo build --target wasm32-unknown-unknown --release ``` -------------------------------- ### Form Data Parsing in Rust Source: https://context7.com/zen-rs/skyzen/llms.txt Shows how to handle URL-encoded form submissions using Skyzen's `Form` utility. It defines a `LoginForm` struct for deserialization and a `LoginResponse` struct for JSON serialization. The `login` function processes the form data. ```rust use serde::{Deserialize, Serialize}; use skyzen:: routing::{CreateRouteNode, Route, Router}, utils::{Form, Json}, ; #[derive(Debug, Deserialize)] struct LoginForm { username: String, password: String, } #[derive(Serialize)] struct LoginResponse { success: bool, username: String, } async fn login(Form(form): Form) -> Json { Json(LoginResponse { success: form.password == "secret", username: form.username, }) } #[skyzen::main] fn main() -> Router { Route::new(("/login".post(login),)) .build() } // POST /login // Content-Type: application/x-www-form-urlencoded // username=alice&password=secret // -> {"success":true,"username":"alice"} ``` -------------------------------- ### Custom Skyzen Server Implementation Source: https://github.com/zen-rs/skyzen/blob/main/README.md For advanced use cases, such as embedding Skyzen into existing applications or using a custom runtime, you can implement the `Server` trait directly. This provides full control over the executor, connection handling, error recovery, and integration with other infrastructure components. ```rust use skyzen::{Server, Endpoint}; use skyzen_hyper::Hyper; async fn run_custom() { let router = router().build(); let executor = MyExecutor::new(); let connections = my_tcp_listener(); Hyper.serve( executor, |error| eprintln!("Connection error: {error}"), connections, router, ).await; } ``` -------------------------------- ### Edge Deployment Endpoints Source: https://context7.com/zen-rs/skyzen/llms.txt Minimal endpoints for edge deployments, including a health check and a greeting endpoint. ```APIDOC ## GET /health ### Description Provides a health check status. ### Method GET ### Endpoint /health ### Response #### Success Response (200) - **status** (string) - The health status, typically "OK". #### Response Example ``` OK ``` ## GET /hello/{name} ### Description Greets a user by name. ### Method GET ### Endpoint /hello/{name} ### Path Parameters - **name** (string) - Required - The name of the person to greet. ### Response #### Success Response (200) - **greeting** (string) - A personalized greeting message. #### Response Example ``` Hello, [name]! ``` ## GET / ### Description Root endpoint for edge deployments, indicating the function is running. ### Method GET ### Endpoint / ### Response #### Success Response (200) - **message** (string) - A confirmation message. #### Response Example ``` Edge Function Running ``` ``` -------------------------------- ### Article Management API Source: https://context7.com/zen-rs/skyzen/llms.txt Provides comprehensive CRUD operations for articles, including listing, creating, and retrieving individual articles with filtering capabilities. ```APIDOC ## GET /articles ### Description Retrieves a list of articles, optionally filtered by tags or search terms. ### Method GET ### Endpoint /articles ### Query Parameters - **tags** (array[string]) - Optional - Filter articles by a list of tags. - **search** (string) - Optional - Filter articles by a search term in the title or body. ### Request Example ```json { "tags": ["rust", "web"], "search": "introduction" } ``` ### Response #### Success Response (200) - **articles** (array[object]) - A list of article objects. - **id** (string) - The unique identifier of the article. - **title** (string) - The title of the article. - **body** (string) - The content of the article. - **tags** (array[string]) - A list of tags associated with the article. #### Response Example ```json [ { "id": "art-1", "title": "Getting Started with Skyzen", "body": "Skyzen is a powerful framework...", "tags": ["rust", "web", "api"] } ] ``` ## POST /articles ### Description Creates a new article from the provided draft. ### Method POST ### Endpoint /articles ### Request Body - **title** (string) - Required - The title of the new article. - **body** (string) - Required - The content of the new article. - **tags** (array[string]) - Optional - A list of tags for the new article. ### Request Example ```json { "title": "New Article", "body": "This is the content of the new article.", "tags": ["new", "example"] } ``` ### Response #### Success Response (200) - **article** (object) - The newly created article. - **id** (string) - The unique identifier of the article. - **title** (string) - The title of the article. - **body** (string) - The content of the article. - **tags** (array[string]) - A list of tags associated with the article. #### Response Example ```json { "id": "art-2", "title": "New Article", "body": "This is the content of the new article.", "tags": ["new", "example"] } ``` ## GET /articles/{id} ### Description Retrieves a specific article by its unique identifier. ### Method GET ### Endpoint /articles/{id} ### Path Parameters - **id** (string) - Required - The unique identifier of the article to retrieve. ### Response #### Success Response (200) - **article** (object) - The requested article. - **id** (string) - The unique identifier of the article. - **title** (string) - The title of the article. - **body** (string) - The content of the article. - **tags** (array[string]) - A list of tags associated with the article. #### Response Example ```json { "id": "art-1", "title": "Getting Started with Skyzen", "body": "Skyzen is a powerful framework...", "tags": ["rust", "web", "api"] } ``` #### Error Response (404 Not Found) Returned if the article with the specified ID does not exist. ``` -------------------------------- ### Project: /zen-rs/skyzen - Error Handling with Custom Error Types Source: https://context7.com/zen-rs/skyzen/llms.txt Details how to define custom error types with associated HTTP status codes for robust error handling. ```APIDOC ## GET /users/{id} ### Description Retrieves a user by their ID. This endpoint demonstrates custom error handling for scenarios like user not found or invalid input. ### Method GET ### Endpoint /users/{id} #### Path Parameters - **id** (string) - Required - The ID of the user to retrieve. ### Request Example None ### Response #### Success Response (200) - **user** (object) - The user object. - **id** (string) - The ID of the user. - **name** (string) - The name of the user. #### Response Example ```json { "id": "123", "name": "Alice" } ``` #### Error Responses - **404 Not Found**: Returned if the user with the specified ID is not found. #### Response Example ``` "user not found" ``` - **401 Unauthorized**: Returned if invalid credentials are provided (not demonstrated in this specific example but possible with other error types). - **409 Conflict**: Returned if there's a conflict, such as a duplicate email (not demonstrated in this specific example but possible with other error types). ``` -------------------------------- ### Skyzen Extractors and Responders Source: https://github.com/zen-rs/skyzen/blob/main/README.md Skyzen facilitates data extraction from requests using extractors, such as `Params` for path parameters and `Json` for request bodies. It also allows handlers to return any type implementing the `Responder` trait, enabling flexible response generation with types like `Json`, `String`, or `Result`. ```rust use skyzen::utils::Json; use skyzen::routing::Params; async fn create_user( params: Params, Json(body): Json, ) -> Result> { // params and body are automatically extracted } ``` ```rust async fn handler() -> impl Responder { Json(data) // or String, &str, Response, Result, etc. } ```