1
0
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:
svartalf 2019-06-08 00:20:55 +03:00
parent 0ebfd790fc
commit 27a894cab7
5 changed files with 61 additions and 34 deletions

View File

@ -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"

View File

@ -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
View 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()
}

View File

@ -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)
}

View File

@ -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,
},
}
}
}