optimize debug log and apply clippy/fmt suggestions

This commit is contained in:
Guillermo Céspedes Tabárez 2025-05-19 02:41:48 -03:00
parent 0a9f6c1955
commit c8a7271d21
2 changed files with 263 additions and 258 deletions

View File

@ -1,11 +1,39 @@
// Example showcasing the experimental introspection feature. // Example showcasing the experimental introspection feature.
// Run with: `cargo run --features experimental-introspection --example introspection` // Run with: `cargo run --features experimental-introspection --example introspection`
use actix_web::{dev::Service, guard, web, App, HttpResponse, HttpServer, Responder};
use serde::Deserialize;
#[cfg(feature = "experimental-introspection")] #[actix_web::main]
#[actix_web::get("/introspection")] async fn main() -> std::io::Result<()> {
async fn introspection_handler() -> impl Responder { #[cfg(feature = "experimental-introspection")]
{
use actix_web::{dev::Service, guard, web, App, HttpResponse, HttpServer, Responder};
use serde::Deserialize;
// Initialize logging
env_logger::Builder::new()
.filter_level(log::LevelFilter::Debug)
.init();
// Custom guard to check if the Content-Type header is present.
struct ContentTypeGuard;
impl guard::Guard for ContentTypeGuard {
fn check(&self, req: &guard::GuardContext<'_>) -> bool {
req.head()
.headers()
.contains_key(actix_web::http::header::CONTENT_TYPE)
}
}
// Data structure for endpoints that receive JSON.
#[derive(Deserialize)]
struct UserInfo {
username: String,
age: u8,
}
// GET /introspection
#[actix_web::get("/introspection")]
async fn introspection_handler() -> impl Responder {
use std::fmt::Write; use std::fmt::Write;
use actix_web::introspection::{get_registry, initialize_registry}; use actix_web::introspection::{get_registry, initialize_registry};
@ -64,35 +92,124 @@ async fn introspection_handler() -> impl Responder {
} }
HttpResponse::Ok().content_type("text/plain").body(buf) HttpResponse::Ok().content_type("text/plain").body(buf)
}
// Custom guard to check if the Content-Type header is present.
struct ContentTypeGuard;
impl guard::Guard for ContentTypeGuard {
fn check(&self, req: &guard::GuardContext<'_>) -> bool {
req.head()
.headers()
.contains_key(actix_web::http::header::CONTENT_TYPE)
} }
} // GET /api/v1/item/{id} and GET /v1/item/{id}
#[actix_web::get("/item/{id}")]
async fn get_item(path: web::Path<u32>) -> impl Responder {
let id = path.into_inner();
HttpResponse::Ok().body(format!("Requested item with id: {}", id))
}
// Data structure for endpoints that receive JSON. // POST /api/v1/info
#[derive(Deserialize)] #[actix_web::post("/info")]
struct UserInfo { async fn post_user_info(info: web::Json<UserInfo>) -> impl Responder {
username: String, HttpResponse::Ok().json(format!(
age: u8, "User {} with age {} received",
} info.username, info.age
))
}
#[actix_web::main] // /api/v1/guarded
async fn main() -> std::io::Result<()> { async fn guarded_handler() -> impl Responder {
// Initialize logging HttpResponse::Ok().body("Passed the Content-Type guard!")
env_logger::Builder::new() }
.filter_level(log::LevelFilter::Debug)
.init();
// GET /api/v2/hello
async fn hello_v2() -> impl Responder {
HttpResponse::Ok().body("Hello from API v2!")
}
// GET /admin/dashboard
async fn admin_dashboard() -> impl Responder {
HttpResponse::Ok().body("Welcome to the Admin Dashboard!")
}
// GET /admin/settings
async fn get_settings() -> impl Responder {
HttpResponse::Ok().body("Current settings: ...")
}
// POST /admin/settings
async fn update_settings() -> impl Responder {
HttpResponse::Ok().body("Settings have been updated!")
}
// GET and POST on /
async fn root_index() -> impl Responder {
HttpResponse::Ok().body("Welcome to the Root Endpoint!")
}
// Additional endpoints for /extra
fn extra_endpoints(cfg: &mut web::ServiceConfig) {
cfg.service(
web::scope("/extra")
.route(
"/ping",
web::get().to(|| async { HttpResponse::Ok().body("pong") }), // GET /extra/ping
)
.service(
web::resource("/multi")
.route(web::get().to(|| async {
HttpResponse::Ok().body("GET response from /extra/multi")
})) // GET /extra/multi
.route(web::post().to(|| async {
HttpResponse::Ok().body("POST response from /extra/multi")
})), // POST /extra/multi
)
.service(
web::scope("{entities_id:\\d+}")
.service(
web::scope("/secure")
.route(
"",
web::get().to(|| async {
HttpResponse::Ok()
.body("GET response from /extra/secure")
}),
) // GET /extra/{entities_id}/secure/
.route(
"/post",
web::post().to(|| async {
HttpResponse::Ok()
.body("POST response from /extra/secure")
}),
), // POST /extra/{entities_id}/secure/post
)
.wrap_fn(|req, srv| {
println!(
"Request to /extra/secure with id: {}",
req.match_info().get("entities_id").unwrap()
);
let fut = srv.call(req);
async move {
let res = fut.await?;
Ok(res)
}
}),
),
);
}
// Additional endpoints for /foo
fn other_endpoints(cfg: &mut web::ServiceConfig) {
cfg.service(
web::scope("/extra")
.route(
"/ping",
web::post()
.to(|| async { HttpResponse::Ok().body("post from /extra/ping") }), // POST /foo/extra/ping
)
.route(
"/ping",
web::delete()
.to(|| async { HttpResponse::Ok().body("delete from /extra/ping") }), // DELETE /foo/extra/ping
),
);
}
// Create the HTTP server with all the routes and handlers
let server = HttpServer::new(|| { let server = HttpServer::new(|| {
let mut app = App::new() App::new()
// API endpoints under /api // API endpoints under /api
.service( .service(
web::scope("/api") web::scope("/api")
@ -151,129 +268,17 @@ async fn main() -> std::io::Result<()> {
.and(guard::Any(guard::Post())), .and(guard::Any(guard::Post())),
) )
.to(HttpResponse::MethodNotAllowed), .to(HttpResponse::MethodNotAllowed),
); )
.service(introspection_handler)
// Register the introspection handler if the feature is enabled.
#[cfg(feature = "experimental-introspection")]
{
app = app.service(introspection_handler); // GET /introspection
}
app
}) })
.workers(1) .workers(1)
.bind("127.0.0.1:8080")?; .bind("127.0.0.1:8080")?;
server.run().await server.run().await
}
// GET /api/v1/item/{id} and GET /v1/item/{id}
#[actix_web::get("/item/{id}")]
async fn get_item(path: web::Path<u32>) -> impl Responder {
let id = path.into_inner();
HttpResponse::Ok().body(format!("Requested item with id: {}", id))
}
// POST /api/v1/info
#[actix_web::post("/info")]
async fn post_user_info(info: web::Json<UserInfo>) -> impl Responder {
HttpResponse::Ok().json(format!(
"User {} with age {} received",
info.username, info.age
))
}
// /api/v1/guarded
async fn guarded_handler() -> impl Responder {
HttpResponse::Ok().body("Passed the Content-Type guard!")
}
// GET /api/v2/hello
async fn hello_v2() -> impl Responder {
HttpResponse::Ok().body("Hello from API v2!")
}
// GET /admin/dashboard
async fn admin_dashboard() -> impl Responder {
HttpResponse::Ok().body("Welcome to the Admin Dashboard!")
}
// GET /admin/settings
async fn get_settings() -> impl Responder {
HttpResponse::Ok().body("Current settings: ...")
}
// POST /admin/settings
async fn update_settings() -> impl Responder {
HttpResponse::Ok().body("Settings have been updated!")
}
// GET and POST on /
async fn root_index() -> impl Responder {
HttpResponse::Ok().body("Welcome to the Root Endpoint!")
}
// Additional endpoints for /extra
fn extra_endpoints(cfg: &mut web::ServiceConfig) {
cfg.service(
web::scope("/extra")
.route(
"/ping",
web::get().to(|| async { HttpResponse::Ok().body("pong") }), // GET /extra/ping
)
.service(
web::resource("/multi")
.route(
web::get().to(|| async {
HttpResponse::Ok().body("GET response from /extra/multi")
}),
) // GET /extra/multi
.route(web::post().to(|| async {
HttpResponse::Ok().body("POST response from /extra/multi")
})), // POST /extra/multi
)
.service(
web::scope("{entities_id:\\d+}")
.service(
web::scope("/secure")
.route(
"",
web::get().to(|| async {
HttpResponse::Ok().body("GET response from /extra/secure")
}),
) // GET /extra/{entities_id}/secure/
.route(
"/post",
web::post().to(|| async {
HttpResponse::Ok().body("POST response from /extra/secure")
}),
), // POST /extra/{entities_id}/secure/post
)
.wrap_fn(|req, srv| {
println!(
"Request to /extra/secure with id: {}",
req.match_info().get("entities_id").unwrap()
);
let fut = srv.call(req);
async move {
let res = fut.await?;
Ok(res)
} }
}), #[cfg(not(feature = "experimental-introspection"))]
), {
); eprintln!("This example requires the 'experimental-introspection' feature to be enabled.");
} std::process::exit(1);
}
// Additional endpoints for /foo
fn other_endpoints(cfg: &mut web::ServiceConfig) {
cfg.service(
web::scope("/extra")
.route(
"/ping",
web::post().to(|| async { HttpResponse::Ok().body("post from /extra/ping") }), // POST /foo/extra/ping
)
.route(
"/ping",
web::delete().to(|| async { HttpResponse::Ok().body("delete from /extra/ping") }), // DELETE /foo/extra/ping
),
);
} }

View File

@ -195,7 +195,7 @@ pub fn register_rmap(_rmap: &ResourceMap) {
let tree_representation = registry.display(0); let tree_representation = registry.display(0);
log::debug!( log::debug!(
"Introspection Tree:\n{}", "Introspection Tree:\n{}",
tree_representation.trim_matches('\n').to_string() tree_representation.trim_matches('\n')
); );
} }