mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-04-16 09:08:01 -04:00
support serving Access-Control-Allow-Origin header (#19)
support serving Access-Control-Allow-Origin header Closes #17.
This commit is contained in:
parent
760b8d95fb
commit
672a327ee2
@ -58,11 +58,15 @@ Options:
|
|||||||
--sample-file-dir=DIR Set the directory holding video data.
|
--sample-file-dir=DIR Set the directory holding video data.
|
||||||
This is typically on a hard drive.
|
This is typically on a hard drive.
|
||||||
[default: /var/lib/moonfire-nvr/sample]
|
[default: /var/lib/moonfire-nvr/sample]
|
||||||
--ui-dir=DIR Set the directory with the user interface files (.html, .js, etc).
|
--ui-dir=DIR Set the directory with the user interface files
|
||||||
|
(.html, .js, etc).
|
||||||
[default: /usr/local/lib/moonfire-nvr/ui]
|
[default: /usr/local/lib/moonfire-nvr/ui]
|
||||||
--http-addr=ADDR Set the bind address for the unencrypted HTTP server.
|
--http-addr=ADDR Set the bind address for the unencrypted HTTP server.
|
||||||
[default: 0.0.0.0:8080]
|
[default: 0.0.0.0:8080]
|
||||||
--read-only Forces read-only mode / disables recording.
|
--read-only Forces read-only mode / disables recording.
|
||||||
|
--allow-origin=ORIGIN If present, adds a Access-Control-Allow-Origin:
|
||||||
|
header to HTTP responses. This may be useful for
|
||||||
|
Javascript development.
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@ -72,6 +76,7 @@ struct Args {
|
|||||||
flag_http_addr: String,
|
flag_http_addr: String,
|
||||||
flag_ui_dir: String,
|
flag_ui_dir: String,
|
||||||
flag_read_only: bool,
|
flag_read_only: bool,
|
||||||
|
flag_allow_origin: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_shutdown_future(h: &reactor::Handle) -> Box<Future<Item = (), Error = ()>> {
|
fn setup_shutdown_future(h: &reactor::Handle) -> Box<Future<Item = (), Error = ()>> {
|
||||||
@ -101,7 +106,8 @@ pub fn run() -> Result<(), Error> {
|
|||||||
let dir = dir::SampleFileDir::new(&args.flag_sample_file_dir, db.clone()).unwrap();
|
let dir = dir::SampleFileDir::new(&args.flag_sample_file_dir, db.clone()).unwrap();
|
||||||
info!("Database is loaded.");
|
info!("Database is loaded.");
|
||||||
|
|
||||||
let s = web::Service::new(db.clone(), dir.clone(), Some(&args.flag_ui_dir), resolve_zone())?;
|
let s = web::Service::new(db.clone(), dir.clone(), Some(&args.flag_ui_dir),
|
||||||
|
args.flag_allow_origin, resolve_zone())?;
|
||||||
|
|
||||||
// Start a streamer for each camera.
|
// Start a streamer for each camera.
|
||||||
let shutdown_streamers = Arc::new(AtomicBool::new(false));
|
let shutdown_streamers = Arc::new(AtomicBool::new(false));
|
||||||
|
@ -103,6 +103,12 @@ impl From<fmt::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<::hyper::Error> for Error {
|
||||||
|
fn from(err: ::hyper::Error) -> Self {
|
||||||
|
Error{description: String::from(err.description()), cause: Some(Box::new(err))}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<io::Error> for Error {
|
impl From<io::Error> for Error {
|
||||||
fn from(err: io::Error) -> Self {
|
fn from(err: io::Error) -> Self {
|
||||||
Error{description: String::from(err.description()), cause: Some(Box::new(err))}
|
Error{description: String::from(err.description()), cause: Some(Box::new(err))}
|
||||||
|
20
src/web.rs
20
src/web.rs
@ -39,7 +39,7 @@ use futures::{future, stream};
|
|||||||
use futures_cpupool;
|
use futures_cpupool;
|
||||||
use json;
|
use json;
|
||||||
use http_serve;
|
use http_serve;
|
||||||
use hyper::header;
|
use hyper::header::{self, Header};
|
||||||
use hyper::server::{self, Request, Response};
|
use hyper::server::{self, Request, Response};
|
||||||
use mime;
|
use mime;
|
||||||
use mp4;
|
use mp4;
|
||||||
@ -170,6 +170,7 @@ struct ServiceInner {
|
|||||||
db: Arc<db::Database>,
|
db: Arc<db::Database>,
|
||||||
dir: Arc<SampleFileDir>,
|
dir: Arc<SampleFileDir>,
|
||||||
ui_files: HashMap<String, UiFile>,
|
ui_files: HashMap<String, UiFile>,
|
||||||
|
allow_origin: Option<header::AccessControlAllowOrigin>,
|
||||||
pool: futures_cpupool::CpuPool,
|
pool: futures_cpupool::CpuPool,
|
||||||
time_zone_name: String,
|
time_zone_name: String,
|
||||||
}
|
}
|
||||||
@ -383,17 +384,22 @@ impl ServiceInner {
|
|||||||
pub struct Service(Arc<ServiceInner>);
|
pub struct Service(Arc<ServiceInner>);
|
||||||
|
|
||||||
impl Service {
|
impl Service {
|
||||||
pub fn new(db: Arc<db::Database>, dir: Arc<SampleFileDir>, ui_dir: Option<&str>, zone: String)
|
pub fn new(db: Arc<db::Database>, dir: Arc<SampleFileDir>, ui_dir: Option<&str>,
|
||||||
-> Result<Self, Error> {
|
allow_origin: Option<String>, zone: String) -> Result<Self, Error> {
|
||||||
let mut ui_files = HashMap::new();
|
let mut ui_files = HashMap::new();
|
||||||
if let Some(d) = ui_dir {
|
if let Some(d) = ui_dir {
|
||||||
Service::fill_ui_files(d, &mut ui_files);
|
Service::fill_ui_files(d, &mut ui_files);
|
||||||
}
|
}
|
||||||
debug!("UI files: {:#?}", ui_files);
|
debug!("UI files: {:#?}", ui_files);
|
||||||
|
let allow_origin = match allow_origin {
|
||||||
|
None => None,
|
||||||
|
Some(o) => Some(header::AccessControlAllowOrigin::parse_header(&header::Raw::from(o))?),
|
||||||
|
};
|
||||||
Ok(Service(Arc::new(ServiceInner {
|
Ok(Service(Arc::new(ServiceInner {
|
||||||
db,
|
db,
|
||||||
dir,
|
dir,
|
||||||
ui_files,
|
ui_files,
|
||||||
|
allow_origin,
|
||||||
pool: futures_cpupool::Builder::new().pool_size(1).name_prefix("static").create(),
|
pool: futures_cpupool::Builder::new().pool_size(1).name_prefix("static").create(),
|
||||||
time_zone_name: zone,
|
time_zone_name: zone,
|
||||||
})))
|
})))
|
||||||
@ -461,6 +467,11 @@ impl server::Service for Service {
|
|||||||
Path::NotFound => self.0.not_found(),
|
Path::NotFound => self.0.not_found(),
|
||||||
Path::Static => self.0.static_file(&req),
|
Path::Static => self.0.static_file(&req),
|
||||||
};
|
};
|
||||||
|
let res = if let Some(ref o) = self.0.allow_origin {
|
||||||
|
res.map(|resp| resp.with_header(o.clone()))
|
||||||
|
} else {
|
||||||
|
res
|
||||||
|
};
|
||||||
future::result(res.map_err(|e| {
|
future::result(res.map_err(|e| {
|
||||||
error!("error: {}", e);
|
error!("error: {}", e);
|
||||||
hyper::Error::Incomplete
|
hyper::Error::Incomplete
|
||||||
@ -519,7 +530,8 @@ mod bench {
|
|||||||
::std::thread::spawn(move || {
|
::std::thread::spawn(move || {
|
||||||
let addr = "127.0.0.1:0".parse().unwrap();
|
let addr = "127.0.0.1:0".parse().unwrap();
|
||||||
let (db, dir) = (db.db.clone(), db.dir.clone());
|
let (db, dir) = (db.db.clone(), db.dir.clone());
|
||||||
let service = super::Service::new(db.clone(), dir.clone(), None, "".to_owned()).unwrap();
|
let service = super::Service::new(db.clone(), dir.clone(), None, None,
|
||||||
|
"".to_owned()).unwrap();
|
||||||
let server = hyper::server::Http::new()
|
let server = hyper::server::Http::new()
|
||||||
.bind(&addr, move || Ok(service.clone()))
|
.bind(&addr, move || Ok(service.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user