commit fef23ba79d

@ -0,0 +1 @@
DATABASE_URL=D:/Share/Map/MBTiles/中国4-10层卫星地图(G).mbtiles

1
.gitignore vendored

@ -0,0 +1 @@
/target

1539
Cargo.lock generated

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…
Cancel
Save