next-web-dev

Crates.ionext-web-dev
lib.rsnext-web-dev
version0.1.7
created_at2025-04-26 08:09:02.901049+00
updated_at2025-09-06 14:40:34.180626+00
descriptionNext Web Dev!
homepage
repository
max_upload_size
id1650033
size293,574
Listening (yuenxillar)

documentation

README

Next Web Dev

Dev - make everything simpler

Current:
Axum as a web server
Rudi as a dependency injection

And many other excellent crates


use std::{
    collections::HashSet,
    net::SocketAddr,
    sync::{atomic::AtomicU32, Arc},
};

use axum::{extract::ConnectInfo, response::IntoResponse, routing::get};
use next_web_core::{async_trait, context::properties::ApplicationProperties, ApplicationContext};
use next_web_dev::{
    application::Application, middleware::find_singleton::FindSingleton, Singleton,
};
use next_web_macros::Find;
use tokio::sync::Mutex;
use tracing::info;

/// Test application
#[derive(Default, Clone)]
pub struct TestApplication;

#[async_trait]
impl Application for TestApplication {
    async fn init_middleware(&mut self, _properties: &ApplicationProperties) {}

    async fn before_start(&mut self, ctx: &mut ApplicationContext) {
        ctx.insert_singleton_with_name(Arc::new(AtomicU32::new(0)), "requestCount");
        ctx.insert_singleton_with_name(Arc::new(Mutex::new(HashSet::<SocketAddr>::new())),"requestIps");

        // 在这里将实例插入至 ctx 之中
        // Insert the instance into the ctx here
        ctx.insert_singleton_with_name(ApplicationStore::default(), "applicationStoreTwo");
    }

    async fn application_router(&mut self, _ctx: &mut ApplicationContext) -> axum::Router {
        axum::Router::new()
            .route("/hello", get(req_hello))
            .route("/record", get(req_record))
            .route("/recordTwo", get(req_record_two))
    }
}

async fn req_hello() -> impl IntoResponse {
    " Hello Axum! \n Hello Next Web!"
}

async fn req_record(
    // 这里将根据泛型的具体类型进行查找 [ApplicationStore -> applicationStore]
    // Here, we will search based on the specific types of generics [ApplicationStore -> applicationStore]
    FindSingleton(store): FindSingleton<ApplicationStore>,
    ConnectInfo(addr): ConnectInfo<SocketAddr>,
) -> impl IntoResponse {
    store.add(addr).await;
    "Ok"
}

#[Find]
async fn req_record_two(
    // 这里使用变量名搜索单例 [application_store_two -> applicationStoreTwo]
    // Search for singleton using variable names  [application_store_two -> applicationStoreTwo]
    FindSingleton(application_store_two): FindSingleton<ApplicationStore>,
    ConnectInfo(addr): ConnectInfo<SocketAddr>,
) -> impl IntoResponse {
    application_store_two.add(addr).await;
    "Ok"
}

#[Singleton(name = "applicationStore")]
#[derive(Clone)]
pub struct ApplicationStore {
    pub request_count: Arc<AtomicU32>,
    pub request_ips: Arc<Mutex<HashSet<SocketAddr>>>,
}

impl ApplicationStore {
    async fn add(&self, addr: SocketAddr) {
        self.request_count
            .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
        match self.request_ips.lock().await.insert(addr) {
            true => info!("Store add new ip: {}", addr.to_string()),
            false => info!("Ip already exists in store: {}", addr.to_string()),
        }

        info!(
            "Current request count: {}",
            self.request_count
                .load(std::sync::atomic::Ordering::Relaxed)
        )
    }
}

impl Default for ApplicationStore {
    fn default() -> Self {
        Self {
            request_count: Arc::new(AtomicU32::new(u32::MAX / 2)),
            request_ips: Default::default(),
        }
    }
}

#[tokio::main]
async fn main() {
    TestApplication::run().await;
}

Commit count: 0

cargo fmt