Crate coi_actix_web
source ·Expand description
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:
ⓘ
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
:
ⓘ
use coi::Inject;
// Ensure all of your traits inherit from `Inject`
pub trait IService: Inject {
...
}
pub trait IRepository: Inject {
...
}
service.rs
ⓘ
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
ⓘ
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
ⓘ
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
Extensions to
actix-web
’s App
struct