diff options
author | Kjetil Orbekk <kjetil.orbekk@gmail.com> | 2017-06-18 12:41:14 -0400 |
---|---|---|
committer | Kjetil Orbekk <kjetil.orbekk@gmail.com> | 2017-06-18 12:41:14 -0400 |
commit | 0b6e7c0ff2e67624a842125a3992b07cd4769e17 (patch) | |
tree | 0066febfa7305cd999ad0f0e9df97f647075858e /src | |
parent | 96cd53ca31da2eedf3ef38124cd8f07a79443c00 (diff) |
Support base_url.
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/main.rs | 22 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/server.rs | 49 |
3 files changed, 55 insertions, 17 deletions
diff --git a/src/bin/main.rs b/src/bin/main.rs index 245416c..506eba4 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -38,8 +38,8 @@ fn create_admin_user(conn: &rusqlite::Connection) { } } -fn serve(context: systemhttp::server::Context, port: u16) { - let _server = systemhttp::server::serve(context, port).unwrap(); +fn serve(context: systemhttp::server::Context, state: systemhttp::server::State, port: u16) { + let _server = systemhttp::server::serve(context, state, port).unwrap(); println!("Serving on {}", port); } @@ -58,6 +58,10 @@ fn main() { .long("db_file") .takes_value(true) .help("Path to sqlite database")) + .arg(Arg::with_name("base_url") + .long("base_url") + .takes_value(true) + .help("URL to prepend to links (useful with proxies)")) .subcommand(SubCommand::with_name("serve") .about("Start the systemhttpd server")) .subcommand(SubCommand::with_name("create_admin_user") @@ -72,19 +76,25 @@ fn main() { let db_file = matches.value_of("db_file").unwrap(); + let base_url = matches.value_of("base_url").unwrap_or("").to_string(); + env_logger::init().unwrap(); let mut conn = rusqlite::Connection::open(db_file) .expect(format!("opening sqlite database at {}", db_file).as_str()); systemhttp::db::init(&mut conn); - let mut context = systemhttp::server::Context { - base_url: "http://localhost:8080".to_string(), + let context = systemhttp::server::Context { + base_url: base_url, + }; + info!("{:?}", context); + let state = systemhttp::server::State { conn: conn, }; + info!("{:?}", state); match matches.subcommand_name() { - Some("serve") => serve(context, port), - Some("create_admin_user") => create_admin_user(&context.conn), + Some("serve") => serve(context, state, port), + Some("create_admin_user") => create_admin_user(&state.conn), x => panic!("Don't know about subcommand: {:?}", x), } } @@ -15,6 +15,7 @@ extern crate staticfile; extern crate regex; extern crate params; extern crate persistent; +extern crate url; pub mod systemd; pub mod render; diff --git a/src/server.rs b/src/server.rs index c0e9028..4e5b6f3 100644 --- a/src/server.rs +++ b/src/server.rs @@ -16,19 +16,26 @@ use router::Router; use staticfile::Static; use systemd::journal; use systemd::unit; -use persistent::Write; +use persistent::{Read, Write}; use rusqlite::Connection; use db; use auth; +use url; #[derive(Debug)] pub struct Context { pub base_url: String, - pub conn: Connection, } impl iron::typemap::Key for Context { type Value = Context; } +#[derive(Debug)] +pub struct State { + pub conn: Connection, +} +impl iron::typemap::Key for State { + type Value = State; +} #[derive(Default, Debug, Clone)] struct Login { @@ -47,6 +54,22 @@ impl iron_sessionstorage::Value for Login { } } +// Construct an absolute url from base_url if provided, or the request url +// otherwise. +fn url_for(r: &mut Request, path: &str) -> Url { + let context = r.get::<Read<Context>>().unwrap(); + match context.base_url.as_ref() { + "" => { + let mut url: url::Url = r.url.clone().into(); + url.set_path(path); + Url::from_generic_url(url).unwrap() + }, + base_url => { + Url::parse(&format!("{}{}", base_url, path)).unwrap() + } + } +} + fn overview(r: &mut Request) -> IronResult<Response> { let mut _value = try!(r.session().get::<Login>()); @@ -139,16 +162,16 @@ fn authenticate(r: &mut Request) -> IronResult<Response> { }; let hash = { - let mutex = r.get::<Write<Context>>().unwrap(); - let context = mutex.lock().unwrap(); - db::lookup_user(&context.conn, &user).unwrap() + let mutex = r.get::<Write<State>>().unwrap(); + let state = mutex.lock().unwrap(); + db::lookup_user(&state.conn, &user).unwrap() }; if let Some(true) = hash.map(|h| auth::validate(&password, &h)) { let login = Login { user: user.to_string() }; // TODO Make a validated login type info!("User logged in: {:?}", login); r.session().set(login)?; - let url = url_for!(r, "root"); + let url = url_for(r, ""); Ok(Response::with((status::Found, Redirect(url)))) } else { login(r) @@ -157,14 +180,17 @@ fn authenticate(r: &mut Request) -> IronResult<Response> { fn logout(r: &mut Request) -> IronResult<Response> { r.session().set::<Login>(Default::default()); - let url = url_for!(r, "root"); + let url = url_for(r, ""); Ok(Response::with((status::Found, Redirect(url)))) } fn make_renderer(r: &mut Request) -> IronResult<render::Renderer> { let user = get_logged_in_user(r)?.map(|u| u.user); - let base_url = format!("{}", url_for!(r, "root")); - Ok(render::Renderer { base_url: base_url, user: user }) + let context = r.get::<Read<Context>>().unwrap(); + Ok(render::Renderer { + base_url: context.base_url.to_string(), + user: user + }) } fn static_file(r: &mut Request) -> IronResult<Response> { @@ -180,7 +206,7 @@ fn static_file(r: &mut Request) -> IronResult<Response> { }) } -pub fn serve(context: Context, port: u16) -> HttpResult<Listening> { +pub fn serve(context: Context, state: State, port: u16) -> HttpResult<Listening> { // TODO: Use a real secret. let secret = b"secret2".to_vec(); let router = router!( @@ -194,7 +220,8 @@ pub fn serve(context: Context, port: u16) -> HttpResult<Listening> { ); let mut chain = Chain::new(router); chain.link_around(SessionStorage::new(SignedCookieBackend::new(secret))); - chain.link(Write::<Context>::both(context)); + chain.link(Read::<Context>::both(context)); + chain.link(Write::<State>::both(state)); let bind_address = format!("{}:{}", "::", port); Iron::new(chain).http(bind_address.as_str()) } |