mirror of
https://github.com/maplibre/martin.git
synced 2024-12-19 21:01:45 +03:00
feat: add MVT handler
This commit is contained in:
parent
8a44543478
commit
204b132a26
44
Cargo.lock
generated
44
Cargo.lock
generated
@ -2,14 +2,13 @@
|
||||
name = "falcon"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"fallible-iterator 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"iron-cors 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"postgres 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"r2d2_postgres 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -98,11 +97,6 @@ dependencies = [
|
||||
"generic-array 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "error"
|
||||
version = "0.1.9"
|
||||
@ -222,9 +216,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.3.4"
|
||||
name = "iron-cors"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
@ -291,11 +289,6 @@ name = "nodrop"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.7.0"
|
||||
@ -381,7 +374,6 @@ dependencies = [
|
||||
"hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"postgres-protocol 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -455,22 +447,6 @@ dependencies = [
|
||||
"antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.6.0"
|
||||
@ -630,7 +606,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
"checksum crypto-mac 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "779015233ac67d65098614aec748ac1c756ab6677fa2e14cf8b37c08dfed1198"
|
||||
"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a"
|
||||
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
|
||||
"checksum error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e606f14042bb87cc02ef6a14db6c90ab92ed6f62d87e69377bc759fd7987cc"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
"checksum fallible-iterator 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5d48ab1bc11a086628e8cc0cc2c2dc200b884ac05c4b48fb71d6036b6999ff1d"
|
||||
@ -644,7 +619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
|
||||
"checksum iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6e8b9c2247fcf6c6a1151f1156932be5606c9fd6f55a2d7f9fc1cb29386b2f7"
|
||||
"checksum iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2440ae846e7a8c7f9b401db8f6e31b4ea5e7d3688b91761337da7e054520c75b"
|
||||
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
|
||||
"checksum iron-cors 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8a271fc9d686887269d23bb2b7dea4dd628fb640578d4d5d951368882208b88"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
|
||||
"checksum lazy_static 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9e5e58fa1a4c3b915a561a78a22ee0cac6ab97dca2504428bc1cb074375f8d5"
|
||||
@ -656,7 +631,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
||||
"checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
|
||||
"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c9c94f2ef72dc272c6bcc8157ccf2bc7da14f4c58c69059ac2fc48492d6916"
|
||||
@ -675,8 +649,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
|
||||
"checksum scheduled-thread-pool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d9fbe48ead32343b76f544c85953bf260ed39219a8bbbb62cd85f6a00f9644f"
|
||||
"checksum serde 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "0c9cab69e16835717c9b8bd13c29f92b6aa34fe32ce2866b1ab481cf2da8442a"
|
||||
"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e"
|
||||
"checksum sha2 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a"
|
||||
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
|
||||
"checksum stringprep 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
|
||||
|
@ -10,10 +10,9 @@ path = "src/main.rs"
|
||||
[dependencies]
|
||||
url = "1.6.0"
|
||||
regex = "0.2.2"
|
||||
fallible-iterator = "0.1.3"
|
||||
iron = "0.5.1"
|
||||
iron-cors = "0.5.1"
|
||||
persistent = "0.3.0"
|
||||
serde_json = "1.0.6"
|
||||
r2d2 = "0.7.4"
|
||||
r2d2_postgres = "0.13.0"
|
||||
postgres = { version = "0.15.1", features = ["with-serde_json", "with-time", "with-uuid"] }
|
||||
postgres = { version = "0.15.1", features = ["with-time", "with-uuid"] }
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
[![Build Status](https://travis-ci.org/stepankuzmin/falcon.svg?branch=master)](https://travis-ci.org/stepankuzmin/falcon)
|
||||
|
||||
PostgreSQL RESTful API
|
||||
PostGIS [Mapbox Vector Tiles](https://github.com/mapbox/vector-tile-spec) server.
|
||||
|
||||
**Warning: this is experimental**
|
||||
|
||||
|
83
src/main.rs
83
src/main.rs
@ -1,9 +1,8 @@
|
||||
extern crate url;
|
||||
extern crate iron;
|
||||
extern crate regex;
|
||||
extern crate iron_cors;
|
||||
extern crate persistent;
|
||||
extern crate serde_json;
|
||||
extern crate fallible_iterator;
|
||||
|
||||
extern crate r2d2;
|
||||
extern crate r2d2_postgres;
|
||||
@ -15,9 +14,8 @@ use iron::prelude::*;
|
||||
use iron::mime;
|
||||
use iron::status;
|
||||
use iron::typemap::Key;
|
||||
use iron_cors::CorsMiddleware;
|
||||
use persistent::Read;
|
||||
use serde_json::Value;
|
||||
use fallible_iterator::FallibleIterator;
|
||||
|
||||
use r2d2::{Pool, PooledConnection};
|
||||
use r2d2_postgres::{TlsMode, PostgresConnectionManager};
|
||||
@ -36,7 +34,8 @@ fn setup_connection_pool(cn_str: &str, pool_size: u32) -> PostgresPool {
|
||||
|
||||
fn handler(req: &mut Request) -> IronResult<Response> {
|
||||
let url: Url = req.url.clone().into();
|
||||
let re = Regex::new(r"^/(?P<schema>\w*)/(?P<table>\w*).(?P<format>\w*)$").unwrap();
|
||||
let tile_re = r"^/(?P<schema>\w*)/(?P<table>\w*)/(?P<z>\d*)/(?P<x>\d*)/(?P<y>\d*).(?P<format>\w*)$";
|
||||
let re = Regex::new(tile_re).unwrap();
|
||||
match re.captures(&url.path()) {
|
||||
Some(caps) => {
|
||||
println!("{} {} {}", req.method, req.version, req.url);
|
||||
@ -44,60 +43,35 @@ fn handler(req: &mut Request) -> IronResult<Response> {
|
||||
let pool = req.get::<Read<DB>>().unwrap();
|
||||
let conn = pool.get().unwrap();
|
||||
|
||||
match &caps["format"] {
|
||||
"json" => get_json(conn, &caps["schema"], &caps["table"]),
|
||||
"geojson" => get_geojson(conn, &caps["schema"], &caps["table"]),
|
||||
&_ => Ok(Response::with((status::NotFound)))
|
||||
let query = format!(
|
||||
"SELECT ST_AsMVT(q, '{1}', 4096, 'geom') FROM ( \
|
||||
SELECT ST_AsMVTGeom( \
|
||||
geom, \
|
||||
TileBBox({2}, {3}, {4}, 4326), \
|
||||
4096, \
|
||||
256, \
|
||||
true \
|
||||
) AS geom FROM {0}.{1} \
|
||||
) AS q;",
|
||||
&caps["schema"], &caps["table"], &caps["z"], &caps["x"], &caps["y"]
|
||||
);
|
||||
|
||||
match conn.query(&query, &[]) {
|
||||
Ok(rows) => {
|
||||
let content_type = "application/x-protobuf".parse::<mime::Mime>().unwrap();
|
||||
let tile: Vec<u8> = rows.get(0).get("st_asmvt");
|
||||
match tile.len() {
|
||||
0 => Ok(Response::with((content_type, status::NoContent))),
|
||||
_ => Ok(Response::with((content_type, status::Ok, tile)))
|
||||
}
|
||||
},
|
||||
Err(e) => Ok(Response::with((status::InternalServerError, e.to_string())))
|
||||
}
|
||||
},
|
||||
None => Ok(Response::with((status::NotFound)))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_json(conn: PostgresPooledConnection, schema: &str, table: &str) -> IronResult<Response> {
|
||||
let query = format!("select json_agg({1}) from {0}.{1}", schema, table);
|
||||
|
||||
let trans = conn.transaction().unwrap();
|
||||
let stmt = trans.prepare(&query).unwrap();
|
||||
let mut result = stmt.lazy_query(&trans, &[], 1000).unwrap();
|
||||
|
||||
let content_type = "application/json".parse::<mime::Mime>().unwrap();
|
||||
match result.next() {
|
||||
Ok(Some(rows)) => {
|
||||
let result: Value = rows.get("json_agg");
|
||||
let content = serde_json::to_string(&result).unwrap();
|
||||
Ok(Response::with((content_type, status::Ok, content)))
|
||||
},
|
||||
Ok(None) => {
|
||||
let content = "[]";
|
||||
Ok(Response::with((content_type, status::Ok, content)))
|
||||
},
|
||||
Err(e) => Ok(Response::with((status::InternalServerError, e.to_string())))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_geojson(conn: PostgresPooledConnection, schema: &str, table: &str) -> IronResult<Response> {
|
||||
let query = format!("select json_agg({1}) from {0}.{1}", schema, table);
|
||||
|
||||
let trans = conn.transaction().unwrap();
|
||||
let stmt = trans.prepare(&query).unwrap();
|
||||
let mut result = stmt.lazy_query(&trans, &[], 1000).unwrap();
|
||||
|
||||
let content_type = "application/json".parse::<mime::Mime>().unwrap();
|
||||
match result.next() {
|
||||
Ok(Some(rows)) => {
|
||||
let result: Value = rows.get("json_agg");
|
||||
let content = serde_json::to_string(&result).unwrap();
|
||||
Ok(Response::with((content_type, status::Ok, content)))
|
||||
},
|
||||
Ok(None) => {
|
||||
let content = "[]";
|
||||
Ok(Response::with((content_type, status::Ok, content)))
|
||||
},
|
||||
Err(e) => Ok(Response::with((status::InternalServerError, e.to_string())))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let conn_string: String = env::var("DATABASE_URL")
|
||||
.expect("DATABASE_URL must be set");
|
||||
@ -108,6 +82,9 @@ fn main() {
|
||||
let mut middleware = Chain::new(handler);
|
||||
middleware.link(Read::<DB>::both(pool));
|
||||
|
||||
let cors_middleware = CorsMiddleware::with_allow_any(false);
|
||||
middleware.link_around(cors_middleware);
|
||||
|
||||
let port = 3000;
|
||||
let bind_addr = format!("0.0.0.0:{}", port);
|
||||
println!("server has been started on {}.", bind_addr);
|
||||
|
Loading…
Reference in New Issue
Block a user