Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ RUST_LOG=ogcapi=debug,ogcapi_services=debug,ogcapi_client=debug,tower_http=debug
APP_HOST=0.0.0.0
APP_PORT=8484

# PUBLIC_URL=http://example.org

DB_USER=postgres
DB_PASSWORD=password
DB_HOST=localhost
DB_PORT=5433
DB_PORT=5432
DB_NAME=ogcapi

DATABASE_URL=postgresql://postgres:password@localhost:5433/ogcapi
DATABASE_URL=postgresql://postgres:password@localhost:5432/ogcapi

AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Expand Down
14 changes: 8 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Dependencies
run: sudo apt-get update && sudo apt-get install -y libgdal-dev

- name: Checkout
uses: actions/checkout@v4

- name: Setup
run: docker compose up db -d

- name: Load data
run: cargo run -p data-loader -- --input data/ne_110m_populated_places.geojson --collection places

- name: Start service
run: |
cargo run -p demo-service &
cargo run -p cite-service &
npx wait-on http://localhost:8484/

- name: Validate service
Expand All @@ -72,5 +72,7 @@ jobs:
ogc-api-features: true
ogc-api-features-container-tag: 1.9-teamengine-6.0.0-RC2
ogc-api-features-ignore: |-
featureOperation
validateFeatureResponse
validateFeaturesWithLimitResponse_NumberMatched
validateFeaturesResponse_NumberMatched
validateFeaturesWithBoundingBoxResponse_NumberMatched
validateFeaturesWithLimitResponse_NumberMatched
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Async OGC API - Processes execution (jobs).
- Multipart/related response support for raw OGC API - Processes results with multiple outputs.
- Echo process for testing.
- Dedicate `cite-service` for OGC Cite testsuite in CI.
- Make public base url configurable via `PUBLIC_URL` environment variable.

### Fixed

- Respect process execution `response` parameter
- Service URL for OGC API - Features
- Respect process execution `response` parameter.
- Service URL for OGC API - Features.
- Minor issues with OGC API - Features conformance.

### Changed

Expand All @@ -26,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Build documentation for all features.
- Output type for OGC API - Processes trait (execute).
- Changed fields to status database model for OGC API - Processes.
- Consolidate API definition for OGC cite validation.

## [0.3.0] - 2025-04-05

Expand Down
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions examples/cite-service/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "cite-service"
version = "0.1.0"
edition.workspace = true
publish = false


[dependencies]
clap = { version = "4.5", features = ["derive", "env"] }
dotenvy = "0.15.7"
tokio = { version = "1.47", features = ["full"] }
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }

ogcapi = { path = "../../ogcapi", version = "0.3", default-features = false, features = [
"services",
"common",
"features",
"processes",
] }
33 changes: 33 additions & 0 deletions examples/cite-service/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use clap::Parser;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

use ogcapi::{
processes::echo::Echo,
services::{AppState, Config, Service},
};

#[tokio::main]
async fn main() {
// setup env
dotenvy::dotenv().ok();

// setup tracing
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::new(
"cite_service=debug,ogcapi=debug,sqlx=warn",
))
.with(tracing_subscriber::fmt::layer().pretty())
.init();

// Config
let config = Config::parse();

// Application state
let state = AppState::new_from(&config).await;

// Register processes/processors
let state = state.processors(vec![Box::new(Echo)]);

// Build & run with hyper
Service::new_with(&config, state).await.serve().await;
}
2 changes: 1 addition & 1 deletion examples/data-loader/src/geojson.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub async fn load(args: Args) -> anyhow::Result<()> {
..Default::default()
})
.or_else(|| Some(Extent::default())),
crs: vec![Crs::default(), Crs::from_epsg(3857), Crs::from_epsg(2056)],
crs: vec![Crs::default(), Crs::from_epsg(3857)],
storage_crs: Some(Crs::default()),
#[cfg(feature = "stac")]
assets: crate::asset::load_asset_from_path(&args.input).await?,
Expand Down
10 changes: 9 additions & 1 deletion ogcapi-drivers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use ogcapi_types::tiles::TileMatrixSet;
#[cfg(feature = "features")]
use ogcapi_types::{
common::Crs,
features::{Feature, Query as FeatureQuery},
features::{Feature, Query as FeatureQuery, Queryables},
};

#[cfg(any(feature = "features", feature = "stac", feature = "edr"))]
Expand Down Expand Up @@ -60,6 +60,14 @@ pub trait FeatureTransactions: Send + Sync {
collection: &str,
query: &FeatureQuery,
) -> anyhow::Result<FeatureCollection>;

async fn queryables(&self, _collection: &str) -> anyhow::Result<Queryables> {
// Default to nothing is queryable
Ok(Queryables {
queryables: Default::default(),
additional_properties: false,
})
}
}

/// Trait for `STAC` search
Expand Down
1 change: 0 additions & 1 deletion ogcapi-drivers/src/postgres/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ impl CollectionTransactions for Db {
}

async fn list_collections(&self, _query: &Query) -> anyhow::Result<Collections> {
println!("Query collections");
let collections: Option<sqlx::types::Json<Vec<Collection>>> = if cfg!(feature = "stac") {
sqlx::query_scalar(
r#"
Expand Down
43 changes: 34 additions & 9 deletions ogcapi-drivers/src/postgres/feature.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ogcapi_types::{
common::{Bbox, Crs, Datetime, IntervalDatetime},
common::{Authority, Bbox, Crs, Datetime, IntervalDatetime},
features::{Feature, FeatureCollection, Query},
};

Expand Down Expand Up @@ -140,8 +140,11 @@ impl FeatureTransactions for Db {

// bbox
if let Some(bbox) = query.bbox.as_ref() {
// TODO: Properly handle crs and bbox transformation
let bbox_srid: i32 = query.bbox_crs.as_srid();
// coordinate system axis order (OGC and Postgis is lng, lat | EPSG is lat, lng)
let order = match query.bbox_crs.authority {
Authority::OGC => [0, 1, 2, 3],
Authority::EPSG => [1, 0, 3, 2],
};

let c = self.read_collection(collection).await?;
let storage_srid = c
Expand All @@ -150,17 +153,39 @@ impl FeatureTransactions for Db {
.unwrap_or_default()
.as_srid();

let envelope = match bbox {
// TODO: handle antimeridian (lower > upper on axis 1)
let intersection = match bbox {
Bbox::Bbox2D(bbox) => format!(
"ST_MakeEnvelope({}, {}, {}, {}, {})",
bbox[0], bbox[1], bbox[2], bbox[3], bbox_srid
"ST_Intersects(geom, ST_Transform(ST_MakeEnvelope({}, {}, {}, {}, {}), {storage_srid}))",
bbox[order[0]],
bbox[order[1]],
bbox[order[2]],
bbox[order[3]],
query.bbox_crs.as_srid()
),
Bbox::Bbox3D(bbox) => format!(
"ST_MakeEnvelope({}, {}, {}, {}, {})",
bbox[0], bbox[1], bbox[3], bbox[4], bbox_srid
// FIXME: ensure proper height/box transformation handling
r#"ST_3DIntersects(geom, ST_Envelope(ST_Transform(ST_SetSRID(ST_MakeLine(ARRAY[
ST_MakePoint({x1}, {y1}, {z1}),
ST_MakePoint({x2}, {y1}, {z1}),
ST_MakePoint({x1}, {y2}, {z1}),
ST_MakePoint({x2}, {y2}, {z1}),
ST_MakePoint({x1}, {y1}, {z2}),
ST_MakePoint({x2}, {y1}, {z2}),
ST_MakePoint({x1}, {y2}, {z2}),
ST_MakePoint({x2}, {y2}, {z2})
]), {srid}), {storage_srid})))"#,
x1 = bbox[order[0]],
y1 = bbox[order[1]],
z1 = bbox[2],
x2 = bbox[order[2] + 1],
y2 = bbox[order[3] + 1],
z2 = bbox[5],
srid = query.bbox_crs.as_srid()
),
};
where_conditions.push(format!("geom && ST_Transform({envelope}, {storage_srid})"));

where_conditions.push(intersection);
}

// datetime
Expand Down
2 changes: 1 addition & 1 deletion ogcapi-processes/src/gdal_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ mod tests {
collection: "streets-gdal".to_string(),
filter: None,
s_srs: None,
database_url: "postgresql://postgres:password@localhost:5433/ogcapi".to_string(),
database_url: "postgresql://postgres:password@localhost:5432/ogcapi".to_string(),
};

let execute = Execute {
Expand Down
2 changes: 1 addition & 1 deletion ogcapi-processes/src/geojson_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ mod tests {
input: "../data/ne_10m_railroads_north_america.geojson".to_owned(),
collection: "streets-geojson".to_string(),
s_srs: None,
database_url: "postgresql://postgres:password@localhost:5433/ogcapi".to_string(),
database_url: "postgresql://postgres:password@localhost:5432/ogcapi".to_string(),
};

let execute = Execute {
Expand Down
Loading
Loading