commit
fef23ba79d
@ -0,0 +1 @@
|
||||
/target
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "mbtiles_server"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
actix-cors = "0.7.0"
|
||||
actix-web = "4.5.1"
|
||||
dotenvy = "0.15.7"
|
||||
env_logger = "0.11.3"
|
||||
log = "0.4.21"
|
||||
r2d2 = "0.8.10"
|
||||
r2d2_sqlite = "0.24.0"
|
||||
rusqlite = { version = "0.31.0", features = ["bundled"] }
|
@ -0,0 +1,105 @@
|
||||
type Pool = ::r2d2::Pool<::r2d2_sqlite::SqliteConnectionManager>;
|
||||
pub type Connection = ::r2d2::PooledConnection<::r2d2_sqlite::SqliteConnectionManager>;
|
||||
|
||||
fn initialize_db_pool() -> Pool {
|
||||
let conn_spec = std::env::var("DATABASE_URL").expect("DATABASE_URL should be set");
|
||||
let manager = ::r2d2_sqlite::SqliteConnectionManager::file(conn_spec);
|
||||
Pool::new(manager).unwrap()
|
||||
}
|
||||
|
||||
async fn execute(
|
||||
pool: &Pool,
|
||||
zoom_level: String,
|
||||
tile_column: String,
|
||||
tile_row: String,
|
||||
) -> Result<Vec<u8>, actix_web::Error> {
|
||||
let pool = pool.clone();
|
||||
let conn = ::actix_web::web::block(move || pool.get())
|
||||
.await?
|
||||
.map_err(::actix_web::error::ErrorInternalServerError)?;
|
||||
|
||||
let data = ::actix_web::web::block(move || {
|
||||
let mut stmt = conn.prepare("
|
||||
SELECT tile_data FROM tiles WHERE zoom_level = :zoom_level AND tile_column = :tile_column AND tile_row = :tile_row
|
||||
").unwrap();
|
||||
|
||||
let mut rows = stmt
|
||||
.query(&[
|
||||
(":zoom_level", zoom_level.as_str()),
|
||||
(":tile_column", tile_column.as_str()),
|
||||
(":tile_row", tile_row.as_str()),
|
||||
])
|
||||
.unwrap();
|
||||
|
||||
let mut bytes = vec![];
|
||||
|
||||
while let Some(row) = rows.next().unwrap() {
|
||||
bytes = row.get(0).unwrap();
|
||||
}
|
||||
|
||||
bytes
|
||||
}).await.unwrap();
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
#[::actix_web::get("/{z}/{x}/{y}.png")]
|
||||
async fn get_tile(
|
||||
pool: ::actix_web::web::Data<Pool>,
|
||||
info: ::actix_web::web::Path<(u32, i64, i64)>,
|
||||
) -> impl ::actix_web::Responder {
|
||||
let info = info.into_inner();
|
||||
let zoom_level = info.0;
|
||||
let tile_column = info.1;
|
||||
let tile_row = info.2;
|
||||
let tile_row = 2_i64.pow(zoom_level) - tile_row - 1;
|
||||
|
||||
let data = execute(
|
||||
&pool,
|
||||
zoom_level.to_string(),
|
||||
tile_column.to_string(),
|
||||
tile_row.to_string(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
::actix_web::HttpResponse::Ok()
|
||||
.content_type(::actix_web::http::header::ContentType::png())
|
||||
.body(data)
|
||||
}
|
||||
|
||||
#[::actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
::dotenvy::dotenv().ok();
|
||||
|
||||
::env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let pool = initialize_db_pool();
|
||||
|
||||
::log::info!("starting HTTP server at http://127.0.0.1:8080");
|
||||
|
||||
::actix_web::HttpServer::new(move || {
|
||||
::actix_web::App::new()
|
||||
.wrap(
|
||||
::actix_cors::Cors::default()
|
||||
.allowed_origin(
|
||||
&std::env::var("ORIGIN_URL")
|
||||
.unwrap_or(String::from("http://localhost:1420")),
|
||||
)
|
||||
.allowed_methods(vec!["GET"])
|
||||
.allowed_headers(vec![
|
||||
::actix_web::http::header::AUTHORIZATION,
|
||||
::actix_web::http::header::ACCEPT,
|
||||
])
|
||||
.allowed_header(::actix_web::http::header::CONTENT_TYPE)
|
||||
.supports_credentials()
|
||||
.max_age(3600),
|
||||
)
|
||||
.app_data(::actix_web::web::Data::new(pool.clone()))
|
||||
.service(get_tile)
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.workers(2)
|
||||
.run()
|
||||
.await
|
||||
}
|
Loading…
Reference in new issue