## Day 1: First Encounter with Hyperlane I stumbled upon the Hyperlane Rust HTTP framework on GitHub and was immediately captivated by its performance metrics. The official documentation states: > "Hyperlane is a high-performance and lightweight Rust HTTP framework designed to simplify the development of modern web services while balancing flexibility and performance." I decided to use it for my distributed systems course project. I started with the `Cargo.toml` file: ```toml [dependencies] hyperlane = "5.25.1" ``` ## Day 3: The Magic of Context Abstraction Today, I delved into the design of Hyperlane's `Context`. In traditional frameworks, you would retrieve the request method like this: ```rust let method = ctx.get_request().await.get_method(); ``` But Hyperlane offers a more elegant approach: ```rust let method = ctx.get_request_method().await; ``` **My Understanding**: This kind of chained call simplification is akin to Rust's `?` operator—it flattens nested calls and significantly enhances code readability. Hyperlane cleverly auto-generates getter/setter methods, mapping `request.method` to `get_request_method()`. ## Day 5: Routing and HTTP Method Macros While attempting to implement RESTful APIs, I discovered Hyperlane's method macros: ```rust #[methods(get, post)] async fn user_api(ctx: Context) { // Handle GET/POST requests } #[delete] async fn delete_user(ctx: Context) { // Handle DELETE requests } ``` **Encountered Issue**: At first, I forgot to add the `async` keyword to my route functions, which led to a half-hour of confusion due to compiler errors. Rust's asynchronous programming truly demands constant attention to detail! ## Day 7: Response Handling Exploration I spent the entire day studying the response APIs and created a comparison table to aid my understanding: | Operation Type | Example Code | Purpose | | ----------------- | ------------------------------------------------- | ------------------------------------- | | Retrieve Response | `let res: Response = ctx.get_response().await;` | Obtain the complete response object | | Set Status Code | `ctx.set_response_status_code(404).await;` | Set a 404 status | | Send Response | `ctx.set_response_body("Data").send().await;` | Send while maintaining the connection | | Close Immediately | `ctx.set_response_body("Bye").send_once().await;` | Send and immediately close | **Important Discovery**: The difference between `send()` and `send_once()` lies in the maintenance of the TCP connection, which is crucial for long-lived connections. ## Day 10: Middleware Onion Model Through the diagrams in the documentation, I understood the middleware workflow: ```mermaid graph LR A[Request] --> B[Middleware 1] B --> C[Middleware 2] C --> D[Controller] D --> E[Middleware 3] E --> F[Middleware 4] F --> G[Response] ``` **My Implementation**: I wrote a simple logging middleware: ```rust async fn log_middleware(ctx: Context, next: Next) { let start = Instant::now(); println!("-> {} {}", ctx.get_request_method().await, ctx.get_request_path().await); next.run(ctx).await; // Call the next middleware println!("<- {}ms", start.elapsed().as_millis()); } ``` ## Day 14: Practical Route Parameters Today, I implemented a dynamic user interface: ```rust // Register route server.route("/user/{id}", user_handler).await; // Handler function async fn user_handler(ctx: Context) { let user_id = ctx.get_route_param("id").await; let user = db.find_user(user_id).await; ctx.set_response_body_json(&user).await.send().await; } ``` **Pitfall Record**: When initially attempting to use a regex route like `/user/{id:\d+}`, I forgot to escape the backslash, leading to a compilation error. Rust's raw string literals came to the rescue: ```rust server.route(r"/user/{id:\d+}", user_handler).await; ``` ## Day 20: Performance Test Surprise I ran a wrk test on an AWS t2.micro instance: ```bash wrk -c360 -d60s http://localhost:8000/ ``` The results were astonishing (compared to other frameworks I learned in class): | Framework | QPS | | --------- | ------- | | Hyperlane | 324,323 | | Rocket | 298,945 | | Gin (Go) | 242,570 | | Express | 139,412 | **Analysis**: Hyperlane's performance is only 5% lower than pure Tokio, yet it provides a complete web framework functionality. Rust's garbage collector-free nature combined with its asynchronous runtime is truly a powerful performance tool! ## Day 25: Version Compatibility Challenge When upgrading to v4.89+, I encountered lifecycle changes: ```rust // Recommended way to abort a request if should_abort { ctx.aborted().await; // New API in v4.89+ return; } ``` **Lesson Learned**: It's crucial to pin version numbers in projects! The execution order of middleware can be entirely different across versions. I found this evolution diagram on GitHub: ```mermaid graph TD v3[3.0.0] -->|Middleware before routing| v4[4.0.0] v4 -->|Separate request/response middleware| v4_22[4.22.0] v4_22 -->|Add aborted| v4_89[4.89.0] v4_89 -->|Add closed| v5_25[5.25.1] ``` ## Final Course Project Architecture ```mermaid graph TB A[Client] --> B[Nginx] B --> C[Hyperlane Gateway] C --> D[Authentication Middleware] D --> E[Route Distribution] E --> F[User Service] E --> G[Order Service] F --> H[Database] G --> H ``` ## Learning Summary 1. **API Design Philosophy**: Hyperlane's chained call design maintains Rust's elegance. 2. **Performance Secret**: Built on Tokio's asynchronous architecture and zero-copy processing. 3. **Middleware System**: The onion model provides clear extension points. 4. **Routing Flexibility**: A balance between simple parameters and regular expressions. 5. **Version Management**: Carefully read the CHANGELOG to avoid compatibility issues. This exploration has given me a deep appreciation for Rust's potential in the web domain. Although Hyperlane is not as feature-rich as frameworks like Django, it is definitely a secret weapon in scenarios where extreme performance is required! Next, I plan to use its WebSocket capabilities to implement a real-time logging system.