opencloudtiles/tools/
serve.rs

1use crate::{
2	server::{source, TileServer},
3	tools::get_reader,
4};
5use clap::Args;
6
7#[derive(Args)]
8#[command(
9	arg_required_else_help = true,
10	disable_version_flag = true,
11	verbatim_doc_comment
12)]
13pub struct Subcommand {
14	/// one or more tile containers you want to serve
15	/// supported container formats are: *.cloudtiles, *.tar, *.mbtiles
16	/// the url will be generated automatically:
17	///    e.g. "ukraine.cloudtiles" will be served at url "/tiles/ukraine/..."
18	/// you can add a name by using a "#":
19	///    e.g. "overlay.tar#iran-revolution" will serve "overlay.tar" at url "/tiles/iran-revolution/..."
20	#[arg(num_args = 1.., required = true, verbatim_doc_comment)]
21	sources: Vec<String>,
22
23	/// serve via port
24	#[arg(short, long, default_value = "8080")]
25	port: u16,
26
27	/// serve static content at "/static/..." from folder
28	#[arg(
29		short = 's',
30		long,
31		conflicts_with = "static_tar",
32		value_name = "folder"
33	)]
34	static_folder: Option<String>,
35
36	/// serve static content at "/static/..." from tar file
37	#[arg(
38		short = 't',
39		long,
40		conflicts_with = "static_folder",
41		value_name = "file"
42	)]
43	static_tar: Option<String>,
44}
45
46pub fn run(arguments: &Subcommand) {
47	let mut server: TileServer = new_server(arguments);
48
49	println!("serve to http://localhost:{}/", arguments.port);
50
51	arguments.sources.iter().for_each(|string| {
52		let parts: Vec<&str> = string.split('#').collect();
53
54		let (name, reader_source) = match parts.len() {
55			1 => (guess_name(string), string.as_str()),
56			2 => (parts[1], parts[0]),
57			_ => panic!(),
58		};
59
60		let reader = get_reader(reader_source);
61		server.add_source(
62			format!("/tiles/{name}/"),
63			source::TileContainer::from(reader),
64		);
65
66		fn guess_name(path: &str) -> &str {
67			let filename = path.split(&['/', '\\']).last().unwrap();
68			let name = filename.split('.').next().unwrap();
69			name
70		}
71	});
72
73	if arguments.static_folder.is_some() {
74		server.add_source(
75			String::from("/static/"),
76			source::Folder::from(arguments.static_folder.as_ref().unwrap()),
77		);
78	} else if arguments.static_tar.is_some() {
79		server.add_source(
80			String::from("/static/"),
81			source::TarFile::from(arguments.static_tar.as_ref().unwrap()),
82		);
83	}
84
85	let mut list: Vec<(String, String)> = server.iter_url_mapping().collect();
86	list.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
87	list
88		.iter()
89		.for_each(|(url, source)| println!("   {:30}  <-  {}", url.to_owned() + "*", source));
90
91	server.start();
92}
93
94fn new_server(command: &Subcommand) -> TileServer {
95	TileServer::new(command.port)
96}