HTTP Basic Authorization for WebApps server.

This commit is contained in:
Tomasz Drwięga
2016-04-08 16:11:58 +02:00
parent 8f16515d82
commit dab54cf2a7
4 changed files with 70 additions and 24 deletions

View File

@@ -35,6 +35,8 @@ mod apps;
mod page;
mod router;
use router::auth::{Authorization, NoAuth, HttpBasicAuth};
/// Http server.
pub struct WebappServer {
handler: Arc<IoHandler>,
@@ -53,14 +55,25 @@ impl WebappServer {
self.handler.add_delegate(delegate);
}
/// Start server asynchronously and returns result with `Listening` handle on success or an error.
pub fn start_http(&self, addr: &str, threads: usize) -> Result<Listening, WebappServerError> {
/// Asynchronously start server with no authentication,
/// return result with `Listening` handle on success or an error.
pub fn start_unsecure_http(&self, addr: &str, threads: usize) -> Result<Listening, WebappServerError> {
self.start_http(addr, threads, NoAuth)
}
/// Asynchronously start server with `HTTP Basic Authentication`,
/// return result with `Listening` handle on success or an error.
pub fn start_basic_auth_http(&self, addr: &str, threads: usize, username: &str, password: &str) -> Result<Listening, WebappServerError> {
self.start_http(addr, threads, HttpBasicAuth::single_user(username, password))
}
fn start_http<A: Authorization + 'static>(&self, addr: &str, threads: usize, authorization: A) -> Result<Listening, WebappServerError> {
let addr = addr.to_owned();
let handler = self.handler.clone();
let cors_domain = jsonrpc_http_server::AccessControlAllowOrigin::Null;
let rpc = ServerHandler::new(handler, cors_domain);
let router = router::Router::new(rpc, apps::main_page(), apps::all_pages());
let router = router::Router::new(rpc, apps::main_page(), apps::all_pages(), authorization);
try!(hyper::Server::http(addr.as_ref() as &str))
.handle_threads(router, threads)

View File

@@ -29,7 +29,7 @@ pub enum Authorized<'a, 'b> where 'b : 'a {
}
/// Authorization interface
pub trait Authorization {
pub trait Authorization : Send + Sync {
/// Handle authorization process and return `Request` and `Response` when authorization is successful.
fn handle<'b, 'a>(&'a self, req: server::Request<'a, 'b>, res: server::Response<'a>)-> Authorized<'a, 'b>;
}

View File

@@ -18,7 +18,7 @@
//! Processes request handling authorization and dispatching it to proper application.
mod api;
mod auth;
pub mod auth;
use std::sync::Arc;
use hyper;
@@ -27,22 +27,22 @@ use page::Page;
use apps::Pages;
use iron::request::Url;
use jsonrpc_http_server::ServerHandler;
use self::auth::{Authorization, NoAuth, Authorized};
use self::auth::{Authorization, Authorized};
pub struct Router {
auth: NoAuth,
pub struct Router<A: Authorization> {
authorization: A,
rpc: ServerHandler,
api: api::RestApi,
main_page: Box<Page>,
pages: Arc<Pages>,
}
impl server::Handler for Router {
impl<A: Authorization> server::Handler for Router<A> {
fn handle<'b, 'a>(&'a self, req: server::Request<'a, 'b>, res: server::Response<'a>) {
let auth = self.auth.handle(req, res);
let auth = self.authorization.handle(req, res);
if let Authorized::Yes(req, res) = auth {
let (path, req) = Router::extract_request_path(req);
let (path, req) = self.extract_request_path(req);
match path {
Some(ref url) if self.pages.contains_key(url) => {
self.pages.get(url).unwrap().handle(req, res);
@@ -59,11 +59,15 @@ impl server::Handler for Router {
}
}
impl Router {
pub fn new(rpc: ServerHandler, main_page: Box<Page>, pages: Pages) -> Self {
impl<A: Authorization> Router<A> {
pub fn new(
rpc: ServerHandler,
main_page: Box<Page>,
pages: Pages,
authorization: A) -> Self {
let pages = Arc::new(pages);
Router {
auth: NoAuth,
authorization: authorization,
rpc: rpc,
api: api::RestApi { pages: pages.clone() },
main_page: main_page,
@@ -71,7 +75,7 @@ impl Router {
}
}
fn extract_url(req: &server::Request) -> Option<Url> {
fn extract_url(&self, req: &server::Request) -> Option<Url> {
match req.uri {
uri::RequestUri::AbsoluteUri(ref url) => {
match Url::from_generic_url(url.clone()) {
@@ -97,8 +101,8 @@ impl Router {
}
}
fn extract_request_path<'a, 'b>(mut req: server::Request<'a, 'b>) -> (Option<String>, server::Request<'a, 'b>) {
let url = Router::extract_url(&req);
fn extract_request_path<'a, 'b>(&self, mut req: server::Request<'a, 'b>) -> (Option<String>, server::Request<'a, 'b>) {
let url = self.extract_url(&req);
match url {
Some(ref url) if url.path.len() > 1 => {
let part = url.path[0].clone();