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]
|
||||
name = "actix-web-httpauth"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
authors = ["svartalf <self@svartalf.info>"]
|
||||
description = "HTTP authentication schemes for actix-web"
|
||||
readme = "README.md"
|
||||
@ -15,8 +15,9 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "^1.0", default_features = false }
|
||||
futures = "0.1"
|
||||
actix-service = "0.4.0"
|
||||
futures = "0.1"
|
||||
futures-locks = "0.3.3"
|
||||
bytes = "0.4"
|
||||
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://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)
|
||||
![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.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_service::{Service, Transform};
|
||||
use actix_web::dev::{ServiceRequest, ServiceResponse};
|
||||
use actix_web::Error;
|
||||
use futures::future::{self, FutureResult};
|
||||
use futures::{Async, Future, IntoFuture, Poll};
|
||||
use futures_locks::Mutex;
|
||||
|
||||
use crate::extractors::{basic, bearer, AuthExtractor};
|
||||
|
||||
@ -21,11 +22,12 @@ use crate::extractors::{basic, bearer, AuthExtractor};
|
||||
/// the parsed credentials into it.
|
||||
/// In case of successful validation `F` callback
|
||||
/// is required to return the `ServiceRequest` back.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HttpAuthentication<T, F>
|
||||
where
|
||||
T: AuthExtractor,
|
||||
{
|
||||
process_fn: Rc<F>,
|
||||
process_fn: Arc<F>,
|
||||
_extractor: PhantomData<T>,
|
||||
}
|
||||
|
||||
@ -40,7 +42,7 @@ where
|
||||
/// validation callback `F`.
|
||||
pub fn with_fn(process_fn: F) -> HttpAuthentication<T, F> {
|
||||
HttpAuthentication {
|
||||
process_fn: Rc::new(process_fn),
|
||||
process_fn: Arc::new(process_fn),
|
||||
_extractor: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -69,7 +71,7 @@ where
|
||||
/// // or to do something else in a async manner.
|
||||
/// fn validator(
|
||||
/// req: ServiceRequest,
|
||||
/// credentials: BasicAuth,
|
||||
/// credentials: BasicAuth,
|
||||
/// ) -> FutureResult<ServiceRequest, Error> {
|
||||
/// // All users are great and more than welcome!
|
||||
/// future::ok(req)
|
||||
@ -140,7 +142,7 @@ where
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
future::ok(AuthenticationMiddleware {
|
||||
service: Some(service),
|
||||
service: Mutex::new(service),
|
||||
process_fn: self.process_fn.clone(),
|
||||
_extractor: PhantomData,
|
||||
})
|
||||
@ -152,8 +154,8 @@ pub struct AuthenticationMiddleware<S, F, T>
|
||||
where
|
||||
T: AuthExtractor,
|
||||
{
|
||||
service: Option<S>,
|
||||
process_fn: Rc<F>,
|
||||
service: Mutex<S>,
|
||||
process_fn: Arc<F>,
|
||||
_extractor: PhantomData<T>,
|
||||
}
|
||||
|
||||
@ -176,23 +178,24 @@ where
|
||||
|
||||
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
|
||||
self.service
|
||||
.as_mut()
|
||||
.try_lock()
|
||||
.expect("AuthenticationMiddleware was called already")
|
||||
.poll_ready()
|
||||
}
|
||||
|
||||
fn call(&mut self, req: Self::Request) -> Self::Future {
|
||||
let process_fn = self.process_fn.clone();
|
||||
let mut service = self
|
||||
.service
|
||||
.take()
|
||||
.expect("AuthenticationMiddleware was called twice");
|
||||
// Note: cloning the mutex, not the service itself
|
||||
let inner = self.service.clone();
|
||||
|
||||
let f = Extract::new(req)
|
||||
.and_then(move |(req, credentials)| {
|
||||
(process_fn)(req, credentials)
|
||||
})
|
||||
.and_then(move |req| service.call(req));
|
||||
.and_then(move |(req, credentials)| (process_fn)(req, credentials))
|
||||
.and_then(move |req| {
|
||||
inner
|
||||
.lock()
|
||||
.map_err(Into::into)
|
||||
.and_then(|mut service| service.call(req))
|
||||
});
|
||||
|
||||
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> {
|
||||
match self.state {
|
||||
State::YieldStr => {
|
||||
match self.inner.next() {
|
||||
Some(s) => {
|
||||
self.state = State::YieldQuote;
|
||||
Some(s)
|
||||
},
|
||||
None => None,
|
||||
State::YieldStr => match self.inner.next() {
|
||||
Some(s) => {
|
||||
self.state = State::YieldQuote;
|
||||
Some(s)
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
State::YieldQuote => {
|
||||
match self.inner.peek() {
|
||||
Some(_) => {
|
||||
self.state = State::YieldStr;
|
||||
Some("\\\"")
|
||||
},
|
||||
None => None,
|
||||
State::YieldQuote => match self.inner.peek() {
|
||||
Some(_) => {
|
||||
self.state = State::YieldStr;
|
||||
Some("\\\"")
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user