diff --git a/README.md b/README.md index 09ffa11..e8c92e8 100644 --- a/README.md +++ b/README.md @@ -37,53 +37,36 @@ docker build -t pdok/goaf:latest . The geopacakge provider is a minimal config for GeoPackages that tend to be relative small e.g. < 3 GB. ```docker -docker run --rm -v `pwd`/example:/example -e PROVIDER='gpkg' -e PATH_GPKG='/example/addresses.gpkg' -e ENDPOINT='http://localhost:8080' -p 8080:8080 pdok/goaf:latest +docker run --rm -v `pwd`/example:/example -c /example/config-addresses-gpkg-minimal.yaml -p 8080:8080 pdok/goaf:latest ``` ## PostGis -More elaborate config optimised performance for huge db (10M+ records/collection) +More elaborate config optimised performance for huge db (10M+ features/collection) ```docker -docker run -v `pwd`/example:/example -e CONNECTION='postgres://{user}:{password}@{host}:{port}/{database}?sslmode=disable' -e PROVIDER='postgis' -e PATH_CONFIG='/example/config_postgis.yaml' -e ENDPOINT='http://localhost:8080' -p 8080:8080 pdok/goaf:latest +docker run -v `pwd`/example:/example -c /example/config-addresses-postgis-localhost.yaml' -p 8080:8080 pdok/goaf:latest ``` -example table +### Example table ```sql -CREATE TABLE bgt_wfs3_v1.bak +CREATE TABLE addresses.addresses ( - _id text COLLATE pg_catalog."default" NOT NULL, - _version text COLLATE pg_catalog."default", + fid text COLLATE pg_catalog."default" NOT NULL, + offsetid bigint NOT NULL, properties jsonb, - _geom geometry, - _bbox geometry, - _offset_id bigint NOT NULL DEFAULT nextval('bgt_wfs3_v1.bak__offset_id_seq'::regclass), - _created timestamp without time zone, - CONSTRAINT bak_pkey PRIMARY KEY (_id) + geom geometry, + bbox geometry, + + CONSTRAINT addresses_addresses_pk PRIMARY KEY (fid) ) WITH ( OIDS = FALSE ) -``` - -used parameters: -```go -bindHost := flag.String("s", envString("BIND_HOST", "0.0.0.0"), "server internal bind address, default; 0.0.0.0") -bindPort := flag.Int("p", envInt("BIND_PORT",8080), "server internal bind address, default; 8080") - -serviceEndpoint := flag.String("endpoint", envString("ENDPOINT","http://localhost:8080"), "server endpoint for proxy reasons, default; http://localhost:8080") -serviceSpecPath := flag.String("spec", envString("SERVICE_SPEC_PATH","spec/oaf.yml"), "swagger openapi spec") -defaultReturnLimit := flag.Int("limit", envInt("LIMIT",100), "limit, default: 100") -maxReturnLimit := flag.Int("limitmax", envInt("LIMIT_MAX",500), "max limit, default: 1000") -providerName := flag.String("provider", envString("PROVIDER",""), "postgis or gpkg") -gpkgFilePath := flag.String("gpkg", envString("PATH_GPKG",""), "geopackage path") -crsMapFilePath := flag.String("crs", envString("PATH_CRS",""), "crs file path") -configFilePath := flag.String("config", envString("PATH_CONFIG",""), "configfile path") -connectionStr := flag.String("connection", envString("CONNECTION", ""), "configfile path") - -featureIdKey := flag.String("featureId", envString("FEATURE_ID",""), "Default feature identification or else first column definition (fid)") //optional for gpkg provider +CREATE INDEX addresses_geom_sidx ON addresses.addresses USING GIST (geom); +CREATE INDEX addresses_offsetid_idx ON addresses.addresses(offsetid); ``` ## Generate diff --git a/example/config-addresses-gpkg-minimal.yaml b/example/config-addresses-gpkg-minimal.yaml new file mode 100644 index 0000000..1601ef5 --- /dev/null +++ b/example/config-addresses-gpkg-minimal.yaml @@ -0,0 +1,3 @@ +datasource: + gpkg: + file: example/addresses.gpkg diff --git a/example/config-addresses-gpkg.yaml b/example/config-addresses-gpkg.yaml new file mode 100644 index 0000000..0233192 --- /dev/null +++ b/example/config-addresses-gpkg.yaml @@ -0,0 +1,8 @@ +endpoint: http://localhost:8080 +openapi: spec/oaf.json +defaultfeaturelimit: 100 +maxfeaturelimit: 500 +datasource: + gpkg: + file: example/addresses.gpkg + fid: fid \ No newline at end of file diff --git a/example/config-addresses-postgis-localhost.yaml b/example/config-addresses-postgis-localhost.yaml new file mode 100644 index 0000000..acaa7b8 --- /dev/null +++ b/example/config-addresses-postgis-localhost.yaml @@ -0,0 +1,27 @@ +endpoint: http://localhost:8080 +openapi: spec/oaf.json +defaultfeaturelimit: 100 +maxfeaturelimit: 500 +datasource: + postgis: + connection: postgres://docker:docker@localhost:5432/oaf?sslmode=disable + collections: + - schemaname: addresses #database schema name + tablename: addresses #database table/view name + identifier: addresses #collection name in api response + # filter: (l."properties"->'eindRegistratie') is null # extra filtering option is added to where clause + description: INSPIRE Alternative Encoding Addresses #Description of the collection + columns: + geometry: geom #column containing the SFS geometry + # geometryType: POINT # has currently no use + fid: fid #the unique indexed identifier for a given feature + offset: offsetid # extra column to determine next keyset paging, should be numeric, indexed and unique, could be equal to feature id + bbox: bbox #extra column with bounding box selection index for intersects query, simplification and speedup + bbox: [4.709923493810017,53.00079137013467,4.897723983538761,53.18212166845569] # Bounding box of all features can be used to display subset of features + srid: 4326 #the projection of the geometry currently stored in database + # Properties are column names which should be exposed in properties part of the response + jsonb: true + properties: + - properties + bbox: [4.709923493810017,53.00079137013467,4.897723983538761,53.18212166845569] + srid: 4326 \ No newline at end of file diff --git a/example/config-addresses-postgis.yaml b/example/config-addresses-postgis.yaml new file mode 100644 index 0000000..f290dfd --- /dev/null +++ b/example/config-addresses-postgis.yaml @@ -0,0 +1,25 @@ +endpoint: http://localhost:8080 +openapi: spec/oaf.json +defaultfeaturelimit: 100 +maxfeaturelimit: 500 +datasource: + postgis: + connection: postgres://docker:docker@postgis:5432/oaf?sslmode=disable + collections: + - schemaname: addresses #database schema name + tablename: addresses #database table/view name + identifier: addresses #collection name in api response + # filter: (l."properties"->'eindRegistratie') is null # extra filtering option is added to where clause + description: INSPIRE Alternative Encoding Addresses #Description of the collection + columns: + geometry: geom #column containing the SFS geometry + # geometryType: POINT # has currently no use + fid: fid #the unique indexed identifier for a given feature + offset: offsetid # extra column to determine next keyset paging, should be numeric, indexed and unique, could be equal to feature id + bbox: bbox #extra column with bounding box selection index for intersects query, simplification and speedup + bbox: [4.709923493810017,53.00079137013467,4.897723983538761,53.18212166845569] # Bounding box of all features can be used to display subset of features + srid: 4326 #the projection of the geometry currently stored in database + # Properties are column names which should be exposed in properties part of the response + jsonb: true + properties: + - properties diff --git a/example/config_postgis.yaml b/example/config_postgis.yaml deleted file mode 100644 index 52bb972..0000000 --- a/example/config_postgis.yaml +++ /dev/null @@ -1,20 +0,0 @@ -ApplicationId: PostGIS-example -Layers: - - SchemaName: addresses #database schema name - TableName: addresses #database table/view name - Identifier: addresses #collection name in api response - # Filter: (l."properties"->'eindRegistratie') is null # extra filtering option is added to where clause - Description: INSPIRE Alternative Encoding Addresses #Description of the collection - GeometryColumn: geom #column containing the SFS geometry - # GeometryType: POINT # has currently no use - FeatureIDColumn: fid #the unique indexed identifier for a given feature - BBoxGeometryColumn: bbox #extra column with bounding box selection index for intersects query, simplification and speedup - OffsetColumn: offsetid # extra column to determine next keyset paging, should be numeric, indexed and unique, could be equal to feature id - BBox: [4.709923493810017,53.00079137013467,4.897723983538761,53.18212166845569] # Bounding box of all features can be used to display subset of features - SrsId: 4326 #the projection of the geometry currently stored in database - # Features are column names which should be exposed in properties part of the response - FeaturesJSONB: true - Features: - - properties -BBox: [4.709923493810017,53.00079137013467,4.897723983538761,53.18212166845569] # bounding box of all layers -SrsId: 4326 # and the corresponding projection diff --git a/example/config_postgis_bgt_history.yaml b/example/config_postgis_bgt_history.yaml deleted file mode 100644 index ce10299..0000000 --- a/example/config_postgis_bgt_history.yaml +++ /dev/null @@ -1,436 +0,0 @@ -ApplicationId: POSTGIS-PRD -Layers: - - SchemaName: bgt_wfs3_v1 #database schema name - TableName: bak #database table/view name - Identifier: bak #collection name in api response - Description: BGT Bak #Description of the collection - GeometryColumn: _geom #column containing the SFS geometry - GeometryType: GEOMETRY # has currently no use - FeatureIDColumn: _version #the unique indexed identifier for a given feature - BBoxGeometryColumn: _bbox #extra column with bounding box selection index for intersects query, simplification and speedup - OffsetColumn: _offset_id # extra column to determine next keyset paging, should be numeric, indexed and unique, could be equal to feature id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] # Bounding box of all features can be used to display subset of features - SrsId: 28992 #the projection of the geometry currently stored in database - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - # Features are column names which should be exposed in properties part of the response - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: begroeidterreindeel - Identifier: begroeidterreindeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT begroeidterreindeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: buurt - Identifier: buurt - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT buurt - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: functioneelgebied - Identifier: functioneelgebied - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT functioneelgebied - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: gebouwinstallatie - Identifier: gebouwinstallatie - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT gebouwinstallatie - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: kast - Identifier: kast - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT kast - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: kunstwerkdeel - Identifier: kunstwerkdeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT kunstwerkdeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: onbegroeidterreindeel - Identifier: onbegroeidterreindeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT onbegroeidterreindeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: ondersteunendwaterdeel - Identifier: ondersteunendwaterdeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT ondersteunendwaterdeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: ondersteunendwegdeel - Identifier: ondersteunendwegdeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT ondersteunendwegdeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: ongeclassificeerdobject - Identifier: ongeclassificeerdobject - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT ongeclassificeerdobject - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: overbruggingsdeel - Identifier: overbruggingsdeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT overbruggingsdeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: overigbouwwerk - Identifier: overigbouwwerk - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT overigbouwwerk - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: overigescheiding - Identifier: overigescheiding - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT overigescheiding - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: paal - Identifier: paal - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT paal - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: pand - Identifier: pand - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT pand - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: put - Identifier: put - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT put - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: scheiding - Identifier: scheiding - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT scheiding - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: spoor - Identifier: spoor - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT spoor - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: stadsdeel - Identifier: stadsdeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT stadsdeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: straatmeubilair - Identifier: straatmeubilair - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT straatmeubilair - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: tunneldeel - Identifier: tunneldeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT tunneldeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: vegetatieobject - Identifier: vegetatieobject - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT vegetatieobject - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: waterdeel - Identifier: waterdeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT waterdeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: wegdeel - Identifier: wegdeel - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT wegdeel - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: weginrichtingselement - Identifier: weginrichtingselement - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT weginrichtingselement - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties - - SchemaName: bgt_wfs3_v1 - TableName: wijk - Identifier: wijk - Filter: (l."properties"->'eindRegistratie') is null - Description: BGT wijk - GeometryColumn: _geom - GeometryType: GEOMETRY - FeatureIDColumn: _id - BBoxGeometryColumn: _bbox - OffsetColumn: _offset_id - BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] - SrsId: 28992 - VendorSpecificParameters: ['lokaalID','bronhouder'] - FeaturesJSONB: true - Features: - - properties -BBox: [-285401.92, 22598.08, 595401.9199999999, 903401.9199999999] # bounding box of all layers -SrsId: 28992 # and the corresponding projection diff --git a/example/docker-compose.yaml b/example/docker-compose.yaml index 2289440..f66f162 100644 --- a/example/docker-compose.yaml +++ b/example/docker-compose.yaml @@ -3,14 +3,11 @@ services: goaf: build: context: ../ - image: pdok/gogcapi-features + image: pdok/goaf:latest restart: unless-stopped - command: ["wfs-server"] + command: ["oaf-server"] environment: - - CONNECTION=postgres://docker:docker@postgis:5432/oaf?sslmode=disable - - PROVIDER=postgis - - PATH_CONFIG=/config/config_postgis.yaml - - ENDPOINT=http://localhost:8080 + - CONFIG=/config/config-addresses-postgis.yaml ports: - 8080:8080 depends_on: diff --git a/gpkg/README.md b/gpkg/README.md index 1035c92..e490705 100644 --- a/gpkg/README.md +++ b/gpkg/README.md @@ -1,5 +1,5 @@ # Geopackage provider ```go -go run start.go -provider gpkg -gpkg example/addresses.gpkg +go run start.go -c example/config-addresses-gpkg-minimal.yaml ``` diff --git a/gpkg/getfeaturesprovider.go b/gpkg/getfeaturesprovider.go index a79a23c..d2e671c 100644 --- a/gpkg/getfeaturesprovider.go +++ b/gpkg/getfeaturesprovider.go @@ -6,7 +6,6 @@ import ( "net/http" "oaf-server/codegen" "oaf-server/provider" - pc "oaf-server/provider" ) type GetFeaturesProvider struct { @@ -18,9 +17,9 @@ type GetFeaturesProvider struct { func (gp *GeoPackageProvider) NewGetFeaturesProvider(r *http.Request) (codegen.Provider, error) { collectionId, limit, offset, _, bbox, time := codegen.ParametersForGetFeatures(r) - limitParam := pc.ParseLimit(limit, gp.CommonProvider.DefaultReturnLimit, gp.CommonProvider.MaxReturnLimit) - offsetParam := pc.ParseUint(offset, 0) - bboxParam := pc.ParseBBox(bbox, gp.GeoPackage.DefaultBBox) + limitParam := provider.ParseLimit(limit, gp.CommonProvider.DefaultReturnLimit, gp.CommonProvider.MaxReturnLimit) + offsetParam := provider.ParseUint(offset, 0) + bboxParam := provider.ParseBBox(bbox, gp.GeoPackage.DefaultBBox) if time != "" { log.Println("Time selection currently not implemented") @@ -49,7 +48,7 @@ func (gp *GeoPackageProvider) NewGetFeaturesProvider(r *http.Request) (codegen.P for _, feature := range fcGeoJSON.Features { hrefBase := fmt.Sprintf("%s%s/%v", gp.CommonProvider.ServiceEndpoint, path, feature.ID) // /collections - links, _ := pc.CreateFeatureLinks("feature", hrefBase, "self", ct) + links, _ := provider.CreateFeatureLinks("feature", hrefBase, "self", ct) feature.Links = links } @@ -68,14 +67,14 @@ func (gp *GeoPackageProvider) NewGetFeaturesProvider(r *http.Request) (codegen.P // create links hrefBase := fmt.Sprintf("%s%s", gp.CommonProvider.ServiceEndpoint, path) // /collections - links, _ := pc.CreateFeatureLinks("features "+cn.Identifier, hrefBase, "self", ct) - _ = pc.ProcesLinksForParams(links, requestParams) + links, _ := provider.CreateFeatureLinks("features "+cn.Identifier, hrefBase, "self", ct) + _ = provider.ProcesLinksForParams(links, requestParams) // next => offsetParam + limitParam < numbersMatched if (int64(limitParam)) == fcGeoJSON.NumberReturned { - ilinks, _ := pc.CreateFeatureLinks("features "+cn.Identifier, hrefBase, "next", ct) + ilinks, _ := provider.CreateFeatureLinks("features "+cn.Identifier, hrefBase, "next", ct) requestParams.Set("offset", fmt.Sprintf("%d", int64(offsetParam)+int64(limitParam))) - _ = pc.ProcesLinksForParams(ilinks, requestParams) + _ = provider.ProcesLinksForParams(ilinks, requestParams) links = append(links, ilinks...) } diff --git a/gpkg/gpkg.go b/gpkg/gpkg.go index b274676..28ac941 100644 --- a/gpkg/gpkg.go +++ b/gpkg/gpkg.go @@ -39,7 +39,7 @@ type GeoPackage struct { DB *sqlx.DB FeatureIdKey string Layers []GeoPackageLayer - DefaultBBox []float64 + DefaultBBox [4]float64 SrsId int64 } @@ -82,7 +82,7 @@ func NewGeoPackage(filepath string, featureIdKey string) (GeoPackage, error) { log.Printf("| LAYER: %d. ID: %s, SRS_ID: %d, TABLE: %s PK: %s, FEATURES : %v\n", i+1, layer.Identifier, layer.SrsId, layer.Features[0], layer.Features[1], layer.Features[2:]) if i == 0 { - gpkg.DefaultBBox = []float64{layer.MinX, layer.MinY, layer.MaxX, layer.MaxY} + gpkg.DefaultBBox = [4]float64{layer.MinX, layer.MinY, layer.MaxX, layer.MaxY} gpkg.SrsId = layer.SrsId } if layer.MinX < gpkg.DefaultBBox[0] { @@ -158,7 +158,7 @@ func (gpkg *GeoPackage) GetLayers(ctx context.Context, db *sqlx.DB) (result []Ge return } -func (gpkg GeoPackage) GetFeatures(ctx context.Context, db *sqlx.DB, layer GeoPackageLayer, collectionId string, offset uint64, limit uint64, featureId interface{}, bbox []float64) (result *FeatureCollectionGeoJSON, err error) { +func (gpkg GeoPackage) GetFeatures(ctx context.Context, db *sqlx.DB, layer GeoPackageLayer, collectionId string, offset uint64, limit uint64, featureId interface{}, bbox [4]float64) (result *FeatureCollectionGeoJSON, err error) { // Features bit of a hack // layer.Features => tablename, PK, ...FEATURES, assuming create table in sql statement first is PK result = &FeatureCollectionGeoJSON{} if len(bbox) > 4 { diff --git a/postgis/describecollectionprovider.go b/postgis/describecollectionprovider.go index b641571..d51623a 100644 --- a/postgis/describecollectionprovider.go +++ b/postgis/describecollectionprovider.go @@ -21,7 +21,7 @@ func (pp *PostgisProvider) NewDescribeCollectionProvider(r *http.Request) (codeg p := &DescribeCollectionProvider{} p.contenttype = ct - for _, cn := range pp.PostGis.Layers { + for _, cn := range pp.PostGis.Collections { // maybe convert to map, but not thread safe! if cn.Identifier != collectionId { continue diff --git a/postgis/getapiprovider.go b/postgis/getapiprovider.go index bb290bf..4f33757 100644 --- a/postgis/getapiprovider.go +++ b/postgis/getapiprovider.go @@ -48,10 +48,10 @@ func CreateProvidesSpecificParameters(provider *PostgisProvider) *openapi3.T { } // adjust swagger to accommodate individual parameters - for _, layer := range provider.PostGis.Layers { + for _, collection := range provider.PostGis.Collections { for k, v := range provider.Api.Paths { if strings.Contains(k, "{collectionId}") { - k := strings.Replace(k, "{collectionId}", strings.ToLower(layer.TableName), 1) + k := strings.Replace(k, "{collectionId}", strings.ToLower(collection.Tablename), 1) params := openapi3.NewParameters() paramsQueryExists := false @@ -69,7 +69,7 @@ func CreateProvidesSpecificParameters(provider *PostgisProvider) *openapi3.T { } // only add vendor specific parameters to query params are already allowed if paramsQueryExists { - for _, specificParam := range layer.VendorSpecificParameters { + for _, specificParam := range collection.VendorSpecificParameters { sp := openapi3.NewQueryParameter(specificParam) sp.Description = fmt.Sprintf("Vendor specific parameter : %s", specificParam) sp.Required = false diff --git a/postgis/getcollectionsprovider.go b/postgis/getcollectionsprovider.go index 4c3eaf5..afd3f3d 100644 --- a/postgis/getcollectionsprovider.go +++ b/postgis/getcollectionsprovider.go @@ -25,12 +25,12 @@ func (pp *PostgisProvider) NewGetCollectionsProvider(r *http.Request) (codegen.P hrefBase := fmt.Sprintf("%s%s", pp.CommonProvider.ServiceEndpoint, path) // /collections links, _ := provider.CreateLinks("collections ", hrefBase, "self", ct) csInfo.Links = append(csInfo.Links, links...) - for _, cn := range pp.PostGis.Layers { + for _, cn := range pp.PostGis.Collections { clinks, _ := provider.CreateLinks("collection "+cn.Identifier, fmt.Sprintf("%s/%s", hrefBase, cn.Identifier), "item", ct) csInfo.Links = append(csInfo.Links, clinks...) } - for _, cn := range pp.PostGis.Layers { + for _, cn := range pp.PostGis.Collections { cInfo := codegen.Collection{ Id: cn.Identifier, diff --git a/postgis/getfeatureprovider.go b/postgis/getfeatureprovider.go index 4517bdd..57069a9 100644 --- a/postgis/getfeatureprovider.go +++ b/postgis/getfeatureprovider.go @@ -21,7 +21,7 @@ func (pp *PostgisProvider) NewGetFeatureProvider(r *http.Request) (codegen.Provi featureIdParam := featureId bboxParam := pp.PostGis.BBox - p := &GetFeatureProvider{srsid: fmt.Sprintf("EPSG:%d", pp.PostGis.SrsId)} + p := &GetFeatureProvider{srsid: fmt.Sprintf("EPSG:%d", pp.PostGis.Srid)} path := r.URL.Path ct := r.Header.Get("Content-Type") @@ -31,13 +31,13 @@ func (pp *PostgisProvider) NewGetFeatureProvider(r *http.Request) (codegen.Provi p.contenttype = ct - for _, cn := range pp.PostGis.Layers { + for _, cn := range pp.PostGis.Collections { // maybe convert to map, but not thread safe! if cn.Identifier != collectionId { continue } - pathItem := pp.ApiProcessed.Paths.Find("/collections/pand/items/{featureId}") + pathItem := pp.ApiProcessed.Paths.Find("/collections/" + collectionId + "/items/{featureId}") if pathItem == nil { return p, errors.New("Invalid path :" + path) } @@ -71,7 +71,7 @@ func (pp *PostgisProvider) NewGetFeatureProvider(r *http.Request) (codegen.Provi return p, nil } - return p, errors.New("Cannot find layer : " + collectionId) + return p, errors.New("Cannot find collection : " + collectionId) } func (gfp *GetFeatureProvider) Provide() (interface{}, error) { diff --git a/postgis/getfeaturesprovider.go b/postgis/getfeaturesprovider.go index d5bf13b..553aa8a 100644 --- a/postgis/getfeaturesprovider.go +++ b/postgis/getfeaturesprovider.go @@ -30,7 +30,7 @@ func (pp *PostgisProvider) NewGetFeaturesProvider(r *http.Request) (codegen.Prov path := r.URL.Path // collections/{collectionId}/items ct := r.Header.Get("Content-Type") - p := &GetFeaturesProvider{srsid: fmt.Sprintf("EPSG:%d", pp.PostGis.SrsId)} + p := &GetFeaturesProvider{srsid: fmt.Sprintf("EPSG:%d", pp.PostGis.Srid)} if ct == provider.JSONContentType { ct = provider.GEOJSONContentType } @@ -47,7 +47,7 @@ func (pp *PostgisProvider) NewGetFeaturesProvider(r *http.Request) (codegen.Prov } } - for _, cn := range pp.PostGis.Layers { + for _, cn := range pp.PostGis.Collections { // maybe convert to map, but not thread safe! if cn.Identifier != collectionId { continue diff --git a/postgis/initprovider.go b/postgis/initprovider.go index 624313a..b6d545d 100644 --- a/postgis/initprovider.go +++ b/postgis/initprovider.go @@ -11,17 +11,15 @@ type PostgisProvider struct { CommonProvider provider.CommonProvider PostGis Postgis CrsMap map[string]string - configFilePath string - connectionStr string + Config provider.Config Api *openapi3.T ApiProcessed *openapi3.T } -func NewPostgisWithCommonProvider(api *openapi3.T, commonProvider provider.CommonProvider, configPath, connectionStr string) *PostgisProvider { +func NewPostgisWithCommonProvider(api *openapi3.T, commonProvider provider.CommonProvider, config provider.Config) *PostgisProvider { p := &PostgisProvider{ CrsMap: map[string]string{"4326": "http://wfww.opengis.net/def/crs/OGC/1.3/CRS84"}, - configFilePath: configPath, - connectionStr: connectionStr, + Config: config, CommonProvider: commonProvider, Api: api, } @@ -29,7 +27,7 @@ func NewPostgisWithCommonProvider(api *openapi3.T, commonProvider provider.Commo } func (provider *PostgisProvider) Init() (err error) { - provider.PostGis, err = NewPostgis(provider.configFilePath, provider.connectionStr) + provider.PostGis, err = NewPostgis(provider.Config) provider.ApiProcessed = CreateProvidesSpecificParameters(provider) return } diff --git a/postgis/postgis.go b/postgis/postgis.go index a96ac45..baebd21 100644 --- a/postgis/postgis.go +++ b/postgis/postgis.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "log" "oaf-server/provider" "time" @@ -13,62 +12,33 @@ import ( "github.com/go-spatial/geom/encoding/geojson" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" - "gopkg.in/yaml.v2" ) type IdNotFoundError struct { err string } -type PostgisLayer struct { - SchemaName string `yaml:"SchemaName,omitempty"` - TableName string `yaml:"TableName,omitempty"` - Description string `yaml:"Description,omitempty"` - Identifier string `yaml:"Identifier,omitempty"` - Filter string `yaml:"Filter,omitempty"` - GeometryColumn string `yaml:"GeometryColumn,omitempty"` - VendorSpecificParameters []string `yaml:"VendorSpecificParameters,omitempty"` - GeometryType string `yaml:"GeometryType,omitempty"` - FeatureIDColumn string `yaml:"FeatureIDColumn,omitempty"` - OffsetColumn string `yaml:"OffsetColumn,omitempty"` - - BBoxGeometryColumn string `yaml:"BBoxGeometryColumn,omitempty"` - - BBox []float64 `yaml:"BBox,omitempty"` - SrsId int64 `yaml:"SrsId,omitempty"` - FeaturesJSONB bool `yaml:"FeaturesJSONB,omitempty"` - Features []string `yaml:"Features,omitempty"` -} - type Postgis struct { - ApplicationId string `yaml:"ApplicationId,omitempty"` - UserVersion string `yaml:"UserVersion,omitempty"` + ApplicationId string + UserVersion string db *sqlx.DB - Layers []PostgisLayer `yaml:"Layers,omitempty"` - BBox []float64 `yaml:"BBox,omitempty"` - SrsId int64 `yaml:"SrsId,omitempty"` + Collections []provider.Collection + BBox [4]float64 + Srid int64 } -func NewPostgis(configfilePath, connectionStr string) (Postgis, error) { +func NewPostgis(config provider.Config) (Postgis, error) { postgis := Postgis{} - configFile, err := ioutil.ReadFile(configfilePath) - - if err != nil { - log.Printf("Could not find config file: %s", configfilePath) - return postgis, err - } else { - err := yaml.Unmarshal(configFile, &postgis) - - if err != nil { - log.Printf("Could not unmarshal config file: %s", configfilePath) - return postgis, err - } + postgis.ApplicationId = config.ApplicationId + postgis.UserVersion = config.UserVersion - } + db, err := sqlx.Open("postgres", config.Datasource.PostGIS.Connection) - db, err := sqlx.Open("postgres", connectionStr) + postgis.Collections = config.Datasource.Collections + postgis.BBox = config.Datasource.BBox + postgis.Srid = int64(config.Datasource.Srid) if err != nil { return postgis, err @@ -89,7 +59,7 @@ func (postgis Postgis) Close() error { return postgis.db.Close() } -func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer PostgisLayer, whereMap map[string]string, offset uint64, limit uint64, featureId interface{}, bbox []float64) (result FeatureCollectionGeoJSON, err error) { +func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, collection provider.Collection, whereMap map[string]string, offset uint64, limit uint64, featureId interface{}, bbox [4]float64) (result FeatureCollectionGeoJSON, err error) { result = FeatureCollectionGeoJSON{} if len(bbox) > 4 { err = errors.New("bbox with 6 elements not supported") @@ -98,30 +68,30 @@ func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer Postg var FeatureIDColumn string - if layer.FeatureIDColumn == "" { - FeatureIDColumn = layer.Features[0] + if collection.Columns.Fid == "" { + FeatureIDColumn = collection.Properties[0] } else { - FeatureIDColumn = layer.FeatureIDColumn + FeatureIDColumn = collection.Columns.Fid } - tableName := fmt.Sprintf(`%s.%s`, layer.SchemaName, layer.TableName) - selectClause := fmt.Sprintf(`l."%s", st_asgeojson(st_forcesfs(l."%s")) as %s, l."%s"`, FeatureIDColumn, layer.GeometryColumn, layer.GeometryColumn, layer.OffsetColumn) + tableName := fmt.Sprintf(`%s.%s`, collection.Schemaname, collection.Tablename) + selectClause := fmt.Sprintf(`l."%s", st_asgeojson(st_forcesfs(l."%s")) as %s, l."%s"`, FeatureIDColumn, collection.Columns.Geometry, collection.Columns.Geometry, collection.Columns.Offset) // SELECT FEATURES - for _, tf := range layer.Features { - if tf == layer.GeometryColumn || tf == FeatureIDColumn { + for _, tf := range collection.Properties { + if tf == collection.Columns.Geometry || tf == collection.Columns.Fid { continue } selectClause += fmt.Sprintf(`, l."%v"`, tf) } - args := []interface{}{bbox[0], bbox[1], bbox[2], bbox[3], layer.SrsId, offset, limit} + args := []interface{}{bbox[0], bbox[1], bbox[2], bbox[3], collection.Srid, offset, limit} additionalWhere := "" additionalWhereIndex := 8 - if layer.Filter != "" { - additionalWhere += fmt.Sprintf(` %s AND `, layer.Filter) + if collection.Filter != "" { + additionalWhere += fmt.Sprintf(` %s AND `, collection.Filter) } if featureId != nil { @@ -130,7 +100,7 @@ func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer Postg additionalWhereIndex++ } // no JSONB features where clause as usual - if !layer.FeaturesJSONB && len(whereMap) > 0 { + if !collection.Jsonb && len(whereMap) > 0 { for k := range whereMap { additionalWhere = fmt.Sprintf(` l."%s"=$%d AND `, k, additionalWhereIndex) args = append(args, featureId) @@ -138,9 +108,9 @@ func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer Postg } } // JSONB - if layer.FeaturesJSONB && len(whereMap) > 0 { + if collection.Jsonb && len(whereMap) > 0 { // JSONB COLUMN - JSONBColumn := layer.Features[0] + JSONBColumn := collection.Properties[0] //l."properties"@> '{"lokaalID": "G1978.7afeb17a5c384f6bb08c2350e3f15b07"}' data, marshalErr := json.Marshal(whereMap) if marshalErr != nil { @@ -154,7 +124,7 @@ func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer Postg // query information with selection query := fmt.Sprintf(`SELECT %s FROM %s l WHERE %s st_intersects(st_makeenvelope($1,$2,$3,$4,$5), l."%s") AND l."%s" > $6 ORDER BY l."%s" LIMIT $7;`, - selectClause, tableName, additionalWhere, layer.GeometryColumn, layer.OffsetColumn, layer.OffsetColumn) + selectClause, tableName, additionalWhere, collection.Columns.Geometry, collection.Columns.Offset, collection.Columns.Offset) rows, err := db.Queryx(query, args...) if err != nil { @@ -216,7 +186,7 @@ func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer Postg feature.ID = identifier } - case layer.OffsetColumn: + case collection.Columns.Offset: ofsset, ok := vals[i].(int64) if !ok { //log.Printf("unexpected column type for geom field. got %t", vals[i]) @@ -224,7 +194,7 @@ func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer Postg } result.Offset = ofsset - case layer.GeometryColumn: + case collection.Columns.Geometry: geomData, ok := vals[i].(string) if !ok { @@ -240,7 +210,7 @@ func (postgis Postgis) GetFeatures(ctx context.Context, db *sqlx.DB, layer Postg } feature.Geometry = geometry - case layer.BBoxGeometryColumn: + case collection.Columns.BBox: // Skip these columns used for bounding box and zoom filtering continue case "properties": // predefined jsonb diff --git a/provider/config.go b/provider/config.go new file mode 100644 index 0000000..9674127 --- /dev/null +++ b/provider/config.go @@ -0,0 +1,86 @@ +package provider + +import ( + "io/ioutil" + "log" + + "gopkg.in/yaml.v2" +) + +type Config struct { + ApplicationId string `yaml:"applicationid,omitempty"` + UserVersion string `yaml:"userversion,omitempty"` + + Endpoint string `yaml:"endpoint"` + Openapi string `yaml:"openapi"` + DefaultFeatureLimit int `yaml:"defaultfeaturelimit"` + MaxFeatureLimit int `yaml:"maxfeaturelimit"` + Datasource Datasource +} + +type Datasource struct { + Geopackage *Geopackage `yaml:"gpkg"` + PostGIS *PostGIS `yaml:"postgis"` + Collections []Collection `yaml:"collections"` + BBox [4]float64 `yaml:"bbox"` + Srid int `yaml:"srid"` +} + +type Geopackage struct { + File string `yaml:"file"` + Fid string `yaml:"fid"` +} + +type PostGIS struct { + Connection string `yaml:"connection"` +} + +type Collection struct { + Schemaname string `yaml:"schemaname"` + Tablename string `yaml:"tablename"` + Identifier string `yaml:"identifier"` + Description string `yaml:"description"` + Filter string `yaml:"filter,omitempty"` + + Columns *Columns `yaml:"columns"` + Geometrytype string `yaml:"geometrytype,omitempty"` + BBox [4]float64 `yaml:"bbox"` + Srid int `yaml:"srid"` + VendorSpecificParameters []string `yaml:"vendorspecificparameters"` + Jsonb bool `yaml:"jsonb"` + Properties []string `yaml:"properties"` +} + +type Columns struct { + Fid string `yaml:"fid"` + Offset string `yaml:"offset"` + BBox string `yaml:"bbox"` + Geometry string `yaml:"geometry"` +} + +func (c *Config) ReadConfig(path string) { + bytes, err := ioutil.ReadFile(path) + if err != nil { + log.Fatalf("Could not read file from path (%v) with error: %v", path, err) + } + + yaml.Unmarshal(bytes, c) + + // set defaults if none are provided + if c.DefaultFeatureLimit < 1 { + c.DefaultFeatureLimit = 100 + } + + if c.MaxFeatureLimit < 1 { + c.MaxFeatureLimit = 500 + } + + if c.Openapi == "" { + c.Openapi = "spec/oaf.json" + } + + if c.Endpoint == "" { + c.Endpoint = "http://localhost:8080" + } + +} diff --git a/provider/util.go b/provider/util.go index 46a610b..9b5fdfd 100644 --- a/provider/util.go +++ b/provider/util.go @@ -248,7 +248,7 @@ func ParseFloat64(stringValue string, defaultValue float64) float64 { return value } -func ParseBBox(stringValue string, defaultValue []float64) []float64 { +func ParseBBox(stringValue string, defaultValue [4]float64) [4]float64 { if stringValue == "" { return defaultValue } @@ -257,7 +257,7 @@ func ParseBBox(stringValue string, defaultValue []float64) []float64 { return defaultValue } - value := make([]float64, len(bboxValues)) + var value [4]float64 for i, v := range bboxValues { value[i] = ParseFloat64(v, value[i]) } diff --git a/start.go b/start.go index aa67ad0..1d95105 100644 --- a/start.go +++ b/start.go @@ -26,43 +26,23 @@ func main() { bindHost := flag.String("s", envString("BIND_HOST", "0.0.0.0"), "server internal bind address, default; 0.0.0.0") bindPort := flag.Int("p", envInt("BIND_PORT", 8080), "server internal bind address, default; 8080") - serviceEndpoint := flag.String("endpoint", envString("ENDPOINT", "http://localhost:8080"), "server endpoint for proxy reasons, default; http://localhost:8080") - serviceSpecPath := flag.String("spec", envString("SERVICE_SPEC_PATH", "spec/oaf.json"), "swagger openapi spec") - defaultReturnLimit := flag.Int("limit", envInt("LIMIT", 100), "limit, default: 100") - maxReturnLimit := flag.Int("limitmax", envInt("LIMIT_MAX", 500), "max limit, default: 1000") - providerName := flag.String("provider", envString("PROVIDER", ""), "postgis or gpkg") - gpkgFilePath := flag.String("gpkg", envString("PATH_GPKG", ""), "geopackage path") - crsMapFilePath := flag.String("crs", envString("PATH_CRS", ""), "crs file path") - configFilePath := flag.String("config", envString("PATH_CONFIG", ""), "configfile path") - connectionStr := flag.String("connection", envString("CONNECTION", ""), "connection string postgis") - // alternative database configuration - if *connectionStr == "" && *providerName == "postgis" { - withDBHost := flag.String("db-host", envString("DB_HOST", "localhost"), "database host") - withDBPort := flag.Int("db-port", envInt("DB_PORT", 5432), "database port number") - WithDBName := flag.String("db-name", envString("DB_NAME", "pdok"), "database name") - withDBSSL := flag.String("db-ssl-mode", envString("DB_SSL_MODE", "disable"), "ssl-mode") - withDBUser := flag.String("db-user-name", envString("DB_USERNAME", "postgres"), "database username") - withDBPassword := flag.String("db-password", envString("DB_PASSWORD", ""), "database password") - - connectionStrAlt := fmt.Sprintf("host=%s port=%d database=%s sslmode=%s user=%s password=%s", - *withDBHost, *withDBPort, *WithDBName, *withDBSSL, *withDBUser, *withDBPassword) - - connectionStr = &connectionStrAlt - } - - featureIdKey := flag.String("featureId", envString("FEATURE_ID", ""), "Default feature identification or else first column definition (fid)") - + configfilepath := flag.String("c", envString("CONFIG", ""), "configfile path") flag.Parse() + config := &provider.Config{} + config.ReadConfig(*configfilepath) + // stage 1: create server with spec path and limits - apiServer, err := server.NewServer(*serviceEndpoint, *serviceSpecPath, uint64(*defaultReturnLimit), uint64(*maxReturnLimit)) + apiServer, err := server.NewServer(config.Endpoint, config.Openapi, uint64(config.DefaultFeatureLimit), uint64(config.MaxFeatureLimit)) if err != nil { log.Fatal("Server initialisation error:", err) } // stage 2: Create providers based upon provider name - commonProvider := provider.NewCommonProvider(*serviceEndpoint, *serviceSpecPath, uint64(*defaultReturnLimit), uint64(*maxReturnLimit)) - providers := getProvider(apiServer.Openapi, providerName, commonProvider, crsMapFilePath, gpkgFilePath, featureIdKey, configFilePath, connectionStr) + commonProvider := provider.NewCommonProvider(config.Endpoint, config.Openapi, uint64(config.DefaultFeatureLimit), uint64(config.MaxFeatureLimit)) + // providers := getProvider(apiServer.Openapi, providerName, commonProvider, crsMapFilePath, gpkgFilePath, featureIdKey, configFilePath, connectionStr) + + providers := getProvider(apiServer.Openapi, commonProvider, *config) if providers == nil { log.Fatal("Incorrect provider provided valid names are: gpkg, postgis") @@ -99,16 +79,26 @@ func main() { } -func getProvider(api *openapi3.T, providerName *string, commonProvider provider.CommonProvider, crsMapFilePath *string, gpkgFilePath *string, featureIdKey *string, configFilePath *string, connectionStr *string) codegen.Providers { - if *providerName == "gpkg" { - return addGeopackageProviders(api, commonProvider, *crsMapFilePath, *gpkgFilePath, *featureIdKey) - } - if *providerName == "postgis" { - return postgis.NewPostgisWithCommonProvider(api, commonProvider, *configFilePath, *connectionStr) +func getProvider(api *openapi3.T, commonProvider provider.CommonProvider, config provider.Config) codegen.Providers { + if config.Datasource.Geopackage != nil { + return addGeopackageProviders(api, commonProvider, "", config.Datasource.Geopackage.File, config.Datasource.Geopackage.Fid) + } else if config.Datasource.PostGIS != nil { + return postgis.NewPostgisWithCommonProvider(api, commonProvider, config) } + return nil } +// func getProvider(api *openapi3.T, providerName *string, commonProvider provider.CommonProvider, crsMapFilePath *string, gpkgFilePath *string, featureIdKey *string, configFilePath *string, connectionStr *string) codegen.Providers { +// if *providerName == "gpkg" { +// return addGeopackageProviders(api, commonProvider, *crsMapFilePath, *gpkgFilePath, *featureIdKey) +// } +// if *providerName == "postgis" { +// return postgis.NewPostgisWithCommonProvider(api, commonProvider, *configFilePath, *connectionStr) +// } +// return nil +// } + func addHealthHandler(router *server.RegexpHandler) { router.HandleFunc(regexp.MustCompile("/health"), func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200)