diff options
author | Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com> | 2021-05-12 11:53:29 +0000 |
---|---|---|
committer | Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com> | 2021-08-30 17:48:49 +0000 |
commit | 79963079fae23668cb0694834faa5d43d0d99f3b (patch) | |
tree | 033bce5f4ddbe68a639229598f1fca8737cf8257 /src/auth.rs | |
parent | Bump deps (diff) | |
download | miniserve-79963079fae23668cb0694834faa5d43d0d99f3b.tar.gz miniserve-79963079fae23668cb0694834faa5d43d0d99f3b.zip |
Fix clippy::too_many_arguments and rework error ..
... page rendering
Too many arguments are moved around and many of them are already stored
in MiniserveConfig. Many of these are used to render error pages.
To fix this issue, it was necessary to rework error page rendering:
1. Implement `ResponseError` for `ContextualError` so that it can be
returned from service handlers as is and will then be automatically
logged to the console and converted into an error response.
2. At service handler level, all error responses are now rendered as
plain text.
3. 'error_page_middleware' is now responsible for the rendering of the
final error page from plain text reponses.
Signed-off-by: Ali MJ Al-Nasrawy <alimjalnasrawy@gmail.com>
Diffstat (limited to '')
-rw-r--r-- | src/auth.rs | 86 |
1 files changed, 18 insertions, 68 deletions
diff --git a/src/auth.rs b/src/auth.rs index 7c77758..0d97f11 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -1,12 +1,10 @@ use actix_web::dev::{Service, ServiceRequest, ServiceResponse}; -use actix_web::http::{header, StatusCode}; -use actix_web::{HttpRequest, HttpResponse}; +use actix_web::{HttpRequest, ResponseError}; use futures::future::Either; use sha2::{Digest, Sha256, Sha512}; use std::future::{ready, Future}; -use crate::errors::{self, ContextualError}; -use crate::renderer; +use crate::errors::ContextualError; #[derive(Clone, Debug)] /// HTTP Basic authentication parameters @@ -77,86 +75,38 @@ pub fn get_hash<T: Digest>(text: &str) -> Vec<u8> { hasher.finalize().to_vec() } -/// When authentication succedes, return the request to be passed to downstream services. -/// Otherwise, return an error response -fn handle_auth(req: ServiceRequest) -> Result<ServiceRequest, ServiceResponse> { - let (req, pl) = req.into_parts(); +fn handle_auth(req: &HttpRequest) -> Result<(), ContextualError> { let required_auth = &req.app_data::<crate::MiniserveConfig>().unwrap().auth; if required_auth.is_empty() { // auth is disabled by configuration - return Ok(ServiceRequest::from_parts(req, pl)); - } else if let Ok(cred) = BasicAuthParams::try_from_request(&req) { - if match_auth(cred, required_auth) { - return Ok(ServiceRequest::from_parts(req, pl)); - } + return Ok(()); } - // auth failed; render and return the error response - let resp = HttpResponse::Unauthorized() - .append_header(( - header::WWW_AUTHENTICATE, - header::HeaderValue::from_static("Basic realm=\"miniserve\""), - )) - .body(build_unauthorized_response( - &req, - ContextualError::InvalidHttpCredentials, - true, - StatusCode::UNAUTHORIZED, - )); - - Err(ServiceResponse::new(req, resp)) + match BasicAuthParams::try_from_request(req) { + Ok(cred) => match match_auth(cred, required_auth) { + true => Ok(()), + false => Err(ContextualError::InvalidHttpCredentials), + }, + Err(_) => Err(ContextualError::RequireHttpCredentials), + } } pub fn auth_middleware<S>( - req: ServiceRequest, + mut req: ServiceRequest, srv: &S, ) -> impl Future<Output = actix_web::Result<ServiceResponse>> + 'static where S: Service<ServiceRequest, Response = ServiceResponse, Error = actix_web::Error>, S::Future: 'static, { - match handle_auth(req) { - Ok(req) => Either::Left(srv.call(req)), - Err(resp) => Either::Right(ready(Ok(resp))), - } -} - -/// Builds the unauthorized response body -/// The reason why log_error_chain is optional is to handle cases where the auth pop-up appears and when the user clicks Cancel. -/// In those case, we do not log the error to the terminal since it does not really matter. -fn build_unauthorized_response( - req: &HttpRequest, - error: ContextualError, - log_error_chain: bool, - error_code: StatusCode, -) -> String { - let state = req.app_data::<crate::MiniserveConfig>().unwrap(); - let error = ContextualError::HttpAuthenticationError(Box::new(error)); - - if log_error_chain { - errors::log_error_chain(error.to_string()); + match handle_auth(req.parts_mut().0) { + Ok(_) => Either::Left(srv.call(req)), + Err(err) => { + let resp = req.into_response(err.error_response()); + Either::Right(ready(Ok(resp))) + } } - let return_path = match state.random_route { - Some(ref random_route) => format!("/{}", random_route), - None => "/".to_string(), - }; - - renderer::render_error( - &error.to_string(), - error_code, - &return_path, - None, - None, - false, - false, - &state.favicon_route, - &state.css_route, - &state.default_color_scheme, - &state.default_color_scheme_dark, - state.hide_version_footer, - ) - .into_string() } #[rustfmt::skip] |