I have an actix-web
server using HttpAuthentication
middleware to authenticate all requests. The server runs fine and responds correctly to most requests, but occasionally certain requests trigger the error:
thread 'actix-rt:worker:2' panicked at 'AuthenticationMiddleware was called already
A request to the same endpoint will only trigger the error some of the time, so I am not sure what the root cause is.
My main()
function (with only the relevant code included is:
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
// Some configuration code here
HttpServer::new(move || {
App::new()
.wrap(
HttpAuthentication::basic(validator)
)
// other code here
})
.bind(ip)?
.run()
.await
}
The validator
function passed as the process_fn
argument to HttpAuthentication::basic
is:
async fn validator(
req: ServiceRequest,
credentials: BasicAuth,
) -> Result<ServiceRequest, Error> {
let config = req.app_data::<Config>()
.map(|data| data.get_ref().clone())
.unwrap_or_else(Default::default)
.scope("urn:example:channel=HBO&urn:example:rating=G,PG-13");
let username = env::var("USERNAME")
.expect("USERNAME must be set");
let password = env::var("PASSWORD")
.expect("USERNAME must be set");
if credentials.user_id().deref() == username {
match credentials.password() {
Some(pass) => {
if pass.deref() == password {
Ok(req)
} else {
Err(AuthenticationError::from(config).into())
}
}
None => Err(AuthenticationError::from(config).into())
}
} else {
Err(AuthenticationError::from(config).into())
}
}
This function essentially is just checking for the validity of the basic authentication username and password sent in the request. As I understand it, this should be wrapping every endpoint on the server and only allowing authenticated requests through.
What I do not understand is why I am getting this runtime error. Does anyone have any ideas as to why this is happening?