mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-27 17:22:57 +01:00
Fixing the middleware multiple calls panic
This commit is contained in:
parent
0ebfd790fc
commit
27a894cab7
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-web-httpauth"
|
name = "actix-web-httpauth"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
authors = ["svartalf <self@svartalf.info>"]
|
authors = ["svartalf <self@svartalf.info>"]
|
||||||
description = "HTTP authentication schemes for actix-web"
|
description = "HTTP authentication schemes for actix-web"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -15,8 +15,9 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "^1.0", default_features = false }
|
actix-web = { version = "^1.0", default_features = false }
|
||||||
futures = "0.1"
|
|
||||||
actix-service = "0.4.0"
|
actix-service = "0.4.0"
|
||||||
|
futures = "0.1"
|
||||||
|
futures-locks = "0.3.3"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
base64 = "0.10"
|
base64 = "0.10"
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[![Latest Version](https://img.shields.io/crates/v/actix-web-httpauth.svg)](https://crates.io/crates/actix-web-httpauth)
|
[![Latest Version](https://img.shields.io/crates/v/actix-web-httpauth.svg)](https://crates.io/crates/actix-web-httpauth)
|
||||||
[![Latest Version](https://docs.rs/actix-web-httpauth/badge.svg)](https://docs.rs/actix-web-httpauth)
|
[![Latest Version](https://docs.rs/actix-web-httpauth/badge.svg)](https://docs.rs/actix-web-httpauth)
|
||||||
[![dependency status](https://deps.rs/crate/actix-web-httpauth/0.3.0/status.svg)](https://deps.rs/crate/actix-web-httpauth/0.3.0)
|
[![dependency status](https://deps.rs/crate/actix-web-httpauth/0.3.1/status.svg)](https://deps.rs/crate/actix-web-httpauth/0.3.1)
|
||||||
![Build Status](https://travis-ci.org/svartalf/actix-web-httpauth.svg?branch=master)
|
![Build Status](https://travis-ci.org/svartalf/actix-web-httpauth.svg?branch=master)
|
||||||
![Apache 2.0 OR MIT licensed](https://img.shields.io/badge/license-Apache2.0%2FMIT-blue.svg)
|
![Apache 2.0 OR MIT licensed](https://img.shields.io/badge/license-Apache2.0%2FMIT-blue.svg)
|
||||||
|
|
||||||
|
27
examples/middleware.rs
Normal file
27
examples/middleware.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use actix_web::dev::ServiceRequest;
|
||||||
|
use actix_web::{middleware, web, App, Error, HttpServer};
|
||||||
|
|
||||||
|
use futures::future;
|
||||||
|
|
||||||
|
use actix_web_httpauth::extractors::basic::BasicAuth;
|
||||||
|
use actix_web_httpauth::middleware::HttpAuthentication;
|
||||||
|
|
||||||
|
fn validator(
|
||||||
|
req: ServiceRequest,
|
||||||
|
_credentials: BasicAuth,
|
||||||
|
) -> future::FutureResult<ServiceRequest, Error> {
|
||||||
|
future::ok(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
HttpServer::new(|| {
|
||||||
|
let auth = HttpAuthentication::basic(validator);
|
||||||
|
App::new()
|
||||||
|
.wrap(middleware::Logger::default())
|
||||||
|
.wrap(auth)
|
||||||
|
.service(web::resource("/").to(|| "Test\r\n"))
|
||||||
|
})
|
||||||
|
.bind("127.0.0.1:8080")?
|
||||||
|
.workers(1)
|
||||||
|
.run()
|
||||||
|
}
|
@ -1,13 +1,14 @@
|
|||||||
//! HTTP Authentication middleware.
|
//! HTTP Authentication middleware.
|
||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::rc::Rc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use actix_service::{Service, Transform};
|
use actix_service::{Service, Transform};
|
||||||
use actix_web::dev::{ServiceRequest, ServiceResponse};
|
use actix_web::dev::{ServiceRequest, ServiceResponse};
|
||||||
use actix_web::Error;
|
use actix_web::Error;
|
||||||
use futures::future::{self, FutureResult};
|
use futures::future::{self, FutureResult};
|
||||||
use futures::{Async, Future, IntoFuture, Poll};
|
use futures::{Async, Future, IntoFuture, Poll};
|
||||||
|
use futures_locks::Mutex;
|
||||||
|
|
||||||
use crate::extractors::{basic, bearer, AuthExtractor};
|
use crate::extractors::{basic, bearer, AuthExtractor};
|
||||||
|
|
||||||
@ -21,11 +22,12 @@ use crate::extractors::{basic, bearer, AuthExtractor};
|
|||||||
/// the parsed credentials into it.
|
/// the parsed credentials into it.
|
||||||
/// In case of successful validation `F` callback
|
/// In case of successful validation `F` callback
|
||||||
/// is required to return the `ServiceRequest` back.
|
/// is required to return the `ServiceRequest` back.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct HttpAuthentication<T, F>
|
pub struct HttpAuthentication<T, F>
|
||||||
where
|
where
|
||||||
T: AuthExtractor,
|
T: AuthExtractor,
|
||||||
{
|
{
|
||||||
process_fn: Rc<F>,
|
process_fn: Arc<F>,
|
||||||
_extractor: PhantomData<T>,
|
_extractor: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ where
|
|||||||
/// validation callback `F`.
|
/// validation callback `F`.
|
||||||
pub fn with_fn(process_fn: F) -> HttpAuthentication<T, F> {
|
pub fn with_fn(process_fn: F) -> HttpAuthentication<T, F> {
|
||||||
HttpAuthentication {
|
HttpAuthentication {
|
||||||
process_fn: Rc::new(process_fn),
|
process_fn: Arc::new(process_fn),
|
||||||
_extractor: PhantomData,
|
_extractor: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +71,7 @@ where
|
|||||||
/// // or to do something else in a async manner.
|
/// // or to do something else in a async manner.
|
||||||
/// fn validator(
|
/// fn validator(
|
||||||
/// req: ServiceRequest,
|
/// req: ServiceRequest,
|
||||||
/// credentials: BasicAuth,
|
/// credentials: BasicAuth,
|
||||||
/// ) -> FutureResult<ServiceRequest, Error> {
|
/// ) -> FutureResult<ServiceRequest, Error> {
|
||||||
/// // All users are great and more than welcome!
|
/// // All users are great and more than welcome!
|
||||||
/// future::ok(req)
|
/// future::ok(req)
|
||||||
@ -140,7 +142,7 @@ where
|
|||||||
|
|
||||||
fn new_transform(&self, service: S) -> Self::Future {
|
fn new_transform(&self, service: S) -> Self::Future {
|
||||||
future::ok(AuthenticationMiddleware {
|
future::ok(AuthenticationMiddleware {
|
||||||
service: Some(service),
|
service: Mutex::new(service),
|
||||||
process_fn: self.process_fn.clone(),
|
process_fn: self.process_fn.clone(),
|
||||||
_extractor: PhantomData,
|
_extractor: PhantomData,
|
||||||
})
|
})
|
||||||
@ -152,8 +154,8 @@ pub struct AuthenticationMiddleware<S, F, T>
|
|||||||
where
|
where
|
||||||
T: AuthExtractor,
|
T: AuthExtractor,
|
||||||
{
|
{
|
||||||
service: Option<S>,
|
service: Mutex<S>,
|
||||||
process_fn: Rc<F>,
|
process_fn: Arc<F>,
|
||||||
_extractor: PhantomData<T>,
|
_extractor: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,23 +178,24 @@ where
|
|||||||
|
|
||||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||||
self.service
|
self.service
|
||||||
.as_mut()
|
.try_lock()
|
||||||
.expect("AuthenticationMiddleware was called already")
|
.expect("AuthenticationMiddleware was called already")
|
||||||
.poll_ready()
|
.poll_ready()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||||
let process_fn = self.process_fn.clone();
|
let process_fn = self.process_fn.clone();
|
||||||
let mut service = self
|
// Note: cloning the mutex, not the service itself
|
||||||
.service
|
let inner = self.service.clone();
|
||||||
.take()
|
|
||||||
.expect("AuthenticationMiddleware was called twice");
|
|
||||||
|
|
||||||
let f = Extract::new(req)
|
let f = Extract::new(req)
|
||||||
.and_then(move |(req, credentials)| {
|
.and_then(move |(req, credentials)| (process_fn)(req, credentials))
|
||||||
(process_fn)(req, credentials)
|
.and_then(move |req| {
|
||||||
})
|
inner
|
||||||
.and_then(move |req| service.call(req));
|
.lock()
|
||||||
|
.map_err(Into::into)
|
||||||
|
.and_then(|mut service| service.call(req))
|
||||||
|
});
|
||||||
|
|
||||||
Box::new(f)
|
Box::new(f)
|
||||||
}
|
}
|
||||||
|
26
src/utils.rs
26
src/utils.rs
@ -26,24 +26,20 @@ impl<'a> Iterator for Quoted<'a> {
|
|||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::YieldStr => {
|
State::YieldStr => match self.inner.next() {
|
||||||
match self.inner.next() {
|
Some(s) => {
|
||||||
Some(s) => {
|
self.state = State::YieldQuote;
|
||||||
self.state = State::YieldQuote;
|
Some(s)
|
||||||
Some(s)
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
}
|
}
|
||||||
|
None => None,
|
||||||
},
|
},
|
||||||
State::YieldQuote => {
|
State::YieldQuote => match self.inner.peek() {
|
||||||
match self.inner.peek() {
|
Some(_) => {
|
||||||
Some(_) => {
|
self.state = State::YieldStr;
|
||||||
self.state = State::YieldStr;
|
Some("\\\"")
|
||||||
Some("\\\"")
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
}
|
}
|
||||||
}
|
None => None,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user