1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-28 01:32:57 +01:00
actix-extras/examples/middleware_basic.rs

90 lines
2.6 KiB
Rust

use std::borrow::Cow;
use std::io;
use actix_service::{Service, Transform};
use actix_web::{dev, web, App, Error, HttpRequest, HttpServer};
use futures::future::{self, Either, FutureResult};
use futures::Poll;
use actix_web_httpauth::extractors::basic::{BasicAuth, Config};
use actix_web_httpauth::extractors::AuthenticationError;
struct Auth(Config);
impl<S, B> Transform<S> for Auth
where
S: Service<Request = dev::ServiceRequest, Response = dev::ServiceResponse<B>, Error = Error>,
S::Future: 'static,
{
type Request = dev::ServiceRequest;
type Response = dev::ServiceResponse<B>;
type Error = Error;
type Transform = AuthMiddleware<S>;
type InitError = ();
type Future = FutureResult<Self::Transform, Self::InitError>;
fn new_transform(&self, service: S) -> Self::Future {
future::ok(AuthMiddleware {
service,
auth: self.0.clone(),
})
}
}
struct AuthMiddleware<S> {
service: S,
auth: Config,
}
impl<S> AuthMiddleware<S> {
fn valid_user(credentials: &BasicAuth) -> bool {
let user_id = credentials.user_id();
let password = credentials.password();
user_id == "Alladin" && password == Some(&Cow::Borrowed("open sesame"))
}
}
impl<S, B> Service for AuthMiddleware<S>
where
S: Service<Request = dev::ServiceRequest, Response = dev::ServiceResponse<B>, Error = Error>,
S::Future: 'static,
{
type Request = dev::ServiceRequest;
type Response = dev::ServiceResponse<B>;
type Error = Error;
type Future = Either<S::Future, FutureResult<Self::Response, Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
}
fn call(&mut self, mut req: dev::ServiceRequest) -> Self::Future {
let auth = BasicAuth::from_service_request(&mut req, &self.auth);
match auth {
Ok(ref credentials) if Self::valid_user(credentials) => Either::A(self.service.call(req)),
Ok(..) => {
let challenge = self.auth.as_ref().clone();
let error = AuthenticationError::new(challenge);
Either::B(future::err(Self::Error::from(error)))
}
Err(e) => Either::B(future::err(e.into())),
}
}
}
fn index(_req: HttpRequest) -> String {
"Hello, authorized user!".to_string()
}
fn main() -> io::Result<()> {
HttpServer::new(|| {
let config = Config::default().realm("WallyWorld");
App::new().wrap(Auth(config)).service(web::resource("/").to(index))
})
.bind("127.0.0.1:8088")?
.run()
}