pub trait Endpoint: Send {
type Error: HttpError;
// Required method
fn respond(
&mut self,
request: &mut Request,
) -> impl Future<Output = Result<Response, Self::Error>> + Send;
}Expand description
A trait for types that can handle HTTP requests and generate responses.
Endpoints represent the final destination in the HTTP request processing pipeline. They receive a mutable reference to the request (allowing them to consume the body or modify headers) and return a response or error.
§Implementation Notes
- Endpoints must be
Sendto work in async contexts - The request parameter is mutable, allowing body consumption and header modification
- Implementations should handle errors gracefully and return appropriate HTTP status codes
- Endpoints can be combined with middleware for additional functionality
§Examples
§Simple Text Response
use http_kit::{Request, Response, Result, Endpoint, Body, Error};
struct GreetingEndpoint {
name: String,
}
impl Endpoint for GreetingEndpoint {
type Error = Error;
async fn respond(&mut self, _request: &mut Request) -> Result<Response> {
let message = format!("Hello, {}!", self.name);
Ok(Response::new(Body::from_bytes(message)))
}
}§JSON API Endpoint
use http::StatusCode;
use http_kit::{Request, Response, Result, Endpoint, Body, HttpError, BodyError};
use serde::{Serialize, Deserialize};
use thiserror::Error;
#[derive(Debug, Error)]
enum ApiError {
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("body error: {0}")]
Body(#[from] BodyError),
}
impl HttpError for ApiError {
fn status(&self) -> Option<StatusCode> {
match self {
Self::Json(_) => Some(StatusCode::BAD_REQUEST),
Self::Body(_) => Some(StatusCode::INTERNAL_SERVER_ERROR),
}
}
}
#[derive(Serialize, Deserialize)]
struct User { name: String, age: u32 }
struct UserEndpoint;
impl Endpoint for UserEndpoint {
type Error = ApiError;
async fn respond(&mut self, request: &mut Request) -> Result<Response, Self::Error> {
match request.method().as_str() {
"GET" => {
let user = User { name: "Alice".into(), age: 30 };
let body = Body::from_json(&user)?;
Ok(Response::new(body))
}
"POST" => {
let user: User = request
.body_mut()
.into_json()
.await?;
// Process user...
let body = Body::from_json(&user)?;
Ok(Response::new(body))
}
_ => Ok(Response::new(Body::from_bytes("Method Not Allowed")))
}
}
}Required Associated Types§
Required Methods§
Sourcefn respond(
&mut self,
request: &mut Request,
) -> impl Future<Output = Result<Response, Self::Error>> + Send
fn respond( &mut self, request: &mut Request, ) -> impl Future<Output = Result<Response, Self::Error>> + Send
Processes an HTTP request and generates a response.
This method receives a mutable reference to the request, allowing it to:
- Consume the request body with
take_body()or similar methods - Read headers, URI, method, and other request metadata
- Modify request state if needed (though this is less common)
The method should return either a successful Response or an Error
with an appropriate HTTP status code.
§Arguments
request- Mutable reference to the HTTP request being processed
§Examples
use http_kit::{Request, Response, Result, Endpoint, Body, Error};
struct StatusEndpoint;
impl Endpoint for StatusEndpoint {
type Error = Error;
async fn respond(&mut self, request: &mut Request) -> Result<Response> {
let status = format!("Method: {}, URI: {}", request.method(), request.uri());
Ok(Response::new(Body::from_bytes(status)))
}
}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.