[−][src]Crate coi_actix_web
This crate provides a simple Dependency Injection framework for actix-web
.
Example
Note that the following example is heavily minified. Files names don't really matter. For a
more involved example, please see the coi-actix-sample
repository.
In your main binary:
ⓘThis example is not tested
use crate::infrastructure::{RepositoryProvider, PoolProvider}; use crate::service::ServiceProvider; use coi::container; use actix_web::{App, HttpServer}; mod traits; mod infrastructure; mod routes; mod service; fn main() { // container! only expects identifiers, so construct this provider outside let postgres_pool = PoolProvider::<NoTls>::new(/* construct actual pool */); // Build your container let container = container! { pool => postgres_pool.singleton, service => ServiceProvider.scoped, repository => RepositoryProvider.scoped, }; HttpServer::new(move || { App::new() // Make sure to assign it to `app_data` and not `data` .app_data(container.clone()) .configure(routes::data::route_config) }) ... }
traits.rs
:
ⓘThis example is not tested
use coi::Inject; // Ensure all of your traits inherit from `Inject` pub trait IService: Inject { ... } pub trait IRepository: Inject { ... }
service.rs
ⓘThis example is not tested
use crate::traits::IService; use coi::Inject; use std::sync::Arc; // derive `Inject` for all structs that will provide the injectable traits. #[derive(Inject)] #[coi(provides pub dyn IService with Service::new(repository))] struct Service { #[coi(inject)] repository: Arc<dyn IRepository>, } impl IService for Service { ... }
Note: See
coi::Inject
for more examples on how to use#[derive(Inject)]
infrastructure.rs
ⓘThis example is not tested
use crate::traits::IRepository; use coi::Inject; use ...::PostgresPool; #[cfg(feature = "notls")] use ...::NoTls; #[cfg(not(feature = "notls"))] use ...::Tls; #[derive(Inject)] #[coi(provides pub dyn IRepository with Repository::new(pool))] struct Repository { #[cfg(feature = "notls")] #[coi(inject)] pool: PostgresPool<NoTls>, #[cfg(not(feature = "notls"))] #[coi(inject)] pool: PostgresPool<Tls>, } impl IRepository for Repository { ... } #[derive(Inject)] struct Pool<T> where T: ... { pool: PostgresPool<T> } #[derive(Provide)] #[coi(provides pub Pool<T> with Pool::new(self.0.pool))] struct PoolProvider<T> where T: ... { pool: PostgresPool<T> } impl<T> PoolProvider<T> where T: ... { fn new(PostgresPool<T>) -> Self { ... } }
routes.rs
ⓘThis example is not tested
use crate::service::IService; use actix_web::{ web::{self, HttpResponse, ServiceConfig}, Responder, }; use coi_actix_web::inject; use std::sync::Arc; #[inject(coi_crate = "coi")] async fn get( id: web::Path<i64>, #[inject] service: Arc<dyn IService>, ) -> Result<impl Responder, ()> { let name: String = service.get(*id).await.map_err(|e| log::error!("{}", e))?; Ok(HttpResponse::Ok().json(name)) } #[inject(coi_crate = "coi")] async fn get_all(#[inject] service: Arc<dyn IService>) -> Result<impl Responder, ()> { let data: Vec<String> = service.get_all().await.map_err(|e| log::error!("{}", e))?; Ok(HttpResponse::Ok().json(data)) } pub fn route_config(config: &mut ServiceConfig) { config.service( web::scope("/data") .route("", web::get().to(get_all)) .route("/", web::get().to(get_all)) .route("/{id}", web::get().to(get)), ); }
Traits
AppExt | Extensions to |
Attribute Macros
inject | The #inject proc macro should only be applied to functions that will
be passed to |