diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..c5c999aa --- /dev/null +++ b/404.html @@ -0,0 +1,926 @@ + + + +
+ + + + + + + + + + + + + + + + + + +In this section we explore how pygeoapi can be used as a facade, or a bridge, to re-publish web services with different interfaces. These bridges can help organisations migrating from OWS to OGC API.
+A powerful use case for pygeoapi is to provide an OGC API - Features interface over existing Web Feature Service (WFS) +or ESRI FeatureServer endpoints. In this scenario, you lower the barrier and increase the usability of existing services to +a wider audience. Let's set up an API on top of an existing WFS hosted by the city of Florence.
+Update the pygeoapi configuration
+Open the pygeoapi configuration in a text editor.
+Find the line # START - EXERCISE 8 - WFS Proxy
.
Add a new dataset section by uncommenting the lines up to # END - EXERCISE 8 - WFS Proxy
:
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 |
|
Save the file and restart Docker Compose. Navigate to http://localhost:5000/collections +to evaluate whether the new dataset has been published.
+Note these important configuration slices under providers
:
We use the pygeoapi OGR Provider.
+This is the most versatile backend of pygeoapi for supporting numerous formats. Using the GDAL/OGR library (Python bindings) allows pygeoapi to connect to around 80+ Vector Formats.
+We could have used the OGR
Provider instead of the SQLiteGPKG
Provider above in the osm_places-vec
exercise above.
storage_crs
denotes the CRS (Coordinate Reference System) in which the dataset is stored (default is CRS84, i.e. 'longitude, latitude')
crs
is an array of CRSs that can be specified for the Features to be returned (crs=
parameter), or for their bounding box (bbox-crs=
parameter). Default is also CRS84.CRS support effectively allows pygeoapi to reproject the data from its storage CRS (here EPSG:3003) +according to OGC API - Features - Part 2: Coordinate Reference Systems by Reference. +The Advanced section of this workshop will further elaborate pygeoapi CRS support.
+We can use the pygeoapi's WMSFacade provider to publish OGC Web Map Service (WMS) interfaces as OGC API - Maps.
+Let's set up an API on top of an existing WMS on the MapServer Demonstration Server:
+https://demo.mapserver.org/cgi-bin/msautotest
+Note
+Feel free to use an WMS of your choice, as you wish!
+Update the pygeoapi configuration
+Open the pygeoapi configuration in a text editor.
+Find the line ## START - EXERCISE 8 - WMS Proxy
.
Add a new dataset section by uncommenting the lines up to ## END - EXERCISE 8 - WMS Proxy
:
Be sure to keep the proper YAML indentation.
+1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 |
|
Run the following requests in your web browser:
+Tip
+Try with your own bbox and width/height values!
+In this section we'll have a look at how to publish Catalogue Service for the Web (CSW) as OGC API - Records. For that, we will use the pycsw OGC CITE demo CSW service.
+Update the pygeoapi configuration
+Open the pygeoapi configuration in a text editor.
+Find the line # START - EXERCISE 8 - CSW Proxy
.
Add a new dataset section by uncommenting the lines up to # END - EXERCISE 8 - CSW Proxy
:
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 |
|
You can explore the proxied catalogue collection using this endpoints:
+Tip
+Remember that you can use the QGIS client suggested here to explore this API.
+The OGC SensorThings API standard offers RESTfull interfaces to interconnect IoT devices, data, in an open and unified way. Although there are some clients that support this standard, there are many more that support OGC API - Features.
+The pygeoapi SensorThings bridge enables to proxy the SensorThings entities (e.g.: Thing
, Sensor
, DataStream
, ObservedProperty
) into feature collections.
In this section we'll have a look at how to Publish a SensorThings API Thing
as an OGC API - Features collection, which can then be consumed by various clients, like the ones listed here
Update the pygeoapi configuration
+Open the pygeoapi configuration in a text editor.
+Find the line # START - EXERCISE 8 - SensorThings Proxy
.
Add a new dataset section by uncommenting the lines up to # END - EXERCISE 8 - SensorThings Proxy
:
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 |
|
Deployment to cloud infratructure and concepts such as Microservices and Twelve-Factor present specific requirements to +how software is designed and implemented. pygeoapi supports these concepts, having a low footprint on CPU and memory, and does not persist user +state, therefore being able to scale without risks.
+A Docker image is available for pygeoapi. You can run the image locally as:
+docker run -p 5000:80 geopython/pygeoapi:latest
+
Review the pygeoapi Dockerfile
+Notice in the pygeoapi Dockerfile how the open api file is generated as part of the Docker startup script.
+In a typical configuration one would override the default pygeoapi configuration file in the image with a customized one and include the data folder:
+using custom configuration
+docker run -p 5000:80 \
+-v $(pwd)/pygeoapi-config.yml:/pygeoapi/local.config.yml \
+-v $(pwd)/geodata:/geodata https://hub.docker.com/r/geopython/pygeoapi:latest
+
docker run -p 5000:80 -v ${pwd}/pygeoapi-config.yml:/pygeoapi/local.config.yml -v ${pwd}/geodata:/geodata https://hub.docker.com/r/geopython/pygeoapi:latest
+
Alternatively, you can build a fresh Docker image including both the configuration and data for the service.
+FROM geopython/pygeoapi:latest
+COPY ./my.config.yml /pygeoapi/local.config.yml
+
You may have noticed that the pygeoapi configuration file includes a reference to the endpoint on which pygeoapi is published. This configuration should +match the public endpoint of the service (domain, path and port).
+By default the pygeoapi Docker image will run from the root
path /
. If you need to run from a sub-path and have all internal URLs correct you can
+set the SCRIPT_NAME
environment variable.
docker run -p 5000:80 -e SCRIPT_NAME='/mypygeoapi' \
+-v $(pwd)/my.config.yml:/pygeoapi/local.config.yml -it geopython/pygeoapi
+# browse to http://localhost:5000/mypygeoapi
+
Congratulations! You can now deploy pygeopi as a cloud native service.
+ + + + + + + + + + + + + + + + +Starting with version 0.15.0, pygeoapi fully supports OGC API - Features - Part 2: Coordinate Reference Systems by Reference.
+This enables the import and export of any data according to dedicated projections.
+A "projection" is specified with a Coordinate Reference System (CRS) identifier. These are in URI formats
+like http://www.opengis.net/def/crs/OGC/1.3/CRS84
(basically WGS84 in longitude, latitude axis order)
+or the "OpenGIS" format like http://www.opengis.net/def/crs/EPSG/0/4258
. Note that the "EPSG:" format like EPSG:4326
+is outside the scope of the OGC standard.
In particular CRS support allows for the following:
+storageCRS
config option crs
config optioncrs=
query parameter for a collection or collection itembbox-crs=
query parameter to indicate that the bbox=
parameter is encoded in that CRSContent-Crs
denotes the CRS of the Feature(s) in the data returnedSo although GeoJSON mandates WGS84 in longitude, latitude order, the client and server may still agree +on other CRSs.
+Under the hood, pygeoapi uses the well-known pyproj Python wrapper to the PROJ library.
+Read more in the pygeoapi documentation in the CRS Chapter.
+Adding CRS support to pygeoapi collections for the provider
type feature
is as simple as
+for example extending the Exercise 2 config with this snippet:
crs:
+ - http://www.opengis.net/def/crs/OGC/1.3/CRS84
+ - http://www.opengis.net/def/crs/EPSG/0/4258
+ - http://www.opengis.net/def/crs/EPSG/0/3857
+ - http://www.opengis.net/def/crs/EPSG/0/4326
+ storage_crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
+
Axis
+Axis order (are coordinates it longitude, latitude or latitude, longitude order?) in projections is often a source of confusion.
+However the URI format is quite clear on this, at least more than the EPSG:
format.
+So http://www.opengis.net/def/crs/OGC/1.3/CRS84 is longitude, latitude order, while
+http://www.opengis.net/def/crs/EPSG/0/4326 is latitude, longitude order.
In the config below, we basically indicate that the data is stored in WGS84 (longitude, latitude axis order) and can be retrieved
+in CRSs like http://www.opengis.net/def/crs/EPSG/0/4258
(ETRS89 latitude, longitude axis order) etc.
Add CRS to a pygeoapi configuration
+Open the pygeoapi configuration file in a text editor.
+Find the line # START - EXERCISE 2 - firenze-terrain
Update the dataset section with CRS support by replacing it with the snippet below:
+1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 |
|
Now we can inspect the collection metadata and retrieve Features in various CRSs. +We can even do this in the Swagger UI, but using the browser is quite fast and clear.
+Collection Metadata
+Open the URL: +http://localhost:5000/collections/firenze-terrains-vec +Your configured CRSs are displayed at the bottom of the page: "Reference Systems" and "Storage CRS".
+See these in JSON format, also at the bottom: +http://localhost:5000/collections/firenze-terrains-vec?f=json +
.
+ .
+ "crs":[
+ "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
+ "http://www.opengis.net/def/crs/EPSG/0/4258",
+ "http://www.opengis.net/def/crs/EPSG/0/3857",
+ "http://www.opengis.net/def/crs/EPSG/0/4326"
+ ],
+ "storageCRS":"http://www.opengis.net/def/crs/OGC/1.3/CRS84"
+ }
+
Using the CRS query parameter
+Open the URL: +http://localhost:5000/collections/firenze-terrains-vec/items?f=json&crs=http://www.opengis.net/def/crs/EPSG/0/4258
+This is ETRS89, similar to WGS84, but for the European Continent (Datum) and in lat,lon order. This is e.g. used in INSPIRE.
+See these in JSON format, also at the bottom:
+"type":"FeatureCollection",
+ "features":[
+ {
+ "type":"Feature",
+ "geometry":{
+ "type":"MultiPolygon",
+ "coordinates":[
+ [
+ [
+ [
+ 43.77805936835436,
+ 11.23486287997071
+ ],
+ [
+ 43.77809089595012,
+ 11.2348943159564
+ ],
+ [
+ 43.77810038978989,
+ 11.23491359066035
+ ],
+ [
+ 43.77705757917591,
+ 11.2368990806804
+ .
+ .
+ "crs":[
+ "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
+ "http://www.opengis.net/def/crs/EPSG/0/4258",
+ "http://www.opengis.net/def/crs/EPSG/0/3857",
+ "http://www.opengis.net/def/crs/EPSG/0/4326"
+ ],
+ "storageCRS":"http://www.opengis.net/def/crs/OGC/1.3/CRS84"
+ }
+
If you open the browser development console, you can observe the HTTP response header:
+Content-Crs: <http://www.opengis.net/def/crs/EPSG/0/4258>
(The CRS URI is always enclosed in <
>
)
While pygeoapi is typically run as a standalone application, it is also designed +to enable direct usage via external Python applications in a number of different +design patterns.at multiple levels. From the official documentation, the below +diagram provides an overview of how pygeoapi is designed and architected:
+ +There are two main ways to create a downstream application:
+The core pygeoapi Python API entrypoint is pygeoapi.api.API
, which is initialized with the pygeoapi configuration
+as a Python dict
.
Note
+The pygeoapi core API enables the developer to manage pygeoapi configuration in any number of ways +(file on disk, object storage, database driven, etc.)
+From here, API objects provide a number of functions, most of which require a pygeoapi.api.APIRequest
object
+according to the web framework. Examples include:
Note
+See the official documentation
+for more information about pygeoapi.api.APIRequest
(you can even use your own custom request object as long as it
+satisfies the interface requirements of pygeoapi.api.APIRequest
.
Let's take a look at what a bare bones API integration would look like, using Flask as an example:
+from flask import Flask, make_response, request
+
+from pygeoapi.api import API
+from pygeoapi.util import yaml_load
+
+my_flask_app = Flask(__name__)
+
+with open('my-pygeoapi-config.yml') as fh:
+ my_pygeoapi_config = yaml_load(fh)
+
+my_pygeoapi_api = API(my_pygeoapi_config)
+
+@my_flask_app.route('/my-landing-page-route')
+def my_def():
+
+ headers, status, content = my_pygeoapi_api.landing_page(request)
+
+ response = make_response(content, status)
+
+ if headers:
+ response.headers = headers
+
+ return response
+
Note
+See the official documentation +for more information on the core Python API
+pygeoapi can be installed and used at the web routing level as a dependency in your project. This is pretty much the easier way to leverage the flexibility and the modularity of its architecture. +Once the interfaces are available then the developer can use the preferred framework for serving the frontend application. In practice +the following modules:
+pygeoapi.flask_app.py
for Flask blueprintspygeoapi.starlette_app.py
for Starlette/FastAPIpygeoapi.django_app.py
for Django (ongoing PR)Some examples are available below for developers.
+from flask import Flask
+
+from pygeoapi.flask_app import BLUEPRINT as pygeoapi_blueprint
+
+my_flask_app = Flask(__name__, static_url_path='/static')
+my_flask_app.url_map.strict_slashes = False
+
+# mount all pygeoapi endpoints to /oapi
+my_flask_app.register_blueprint(pygeoapi_blueprint, url_prefix='/oapi')
+
+
+@my_flask_app.route('/')
+def home():
+ return '<p>home page</p>'
+
import uvicorn
+from fastapi import FastAPI
+from fastapi.exceptions import RequestValidationError
+from starlette.exceptions import HTTPException as StarletteHTTPException
+from starlette.middleware.cors import CORSMiddleware
+
+from pygeoapi.starlette_app import app as pygeoapi_app
+
+
+def create_app() -> FastAPI:
+ """Handle application creation."""
+ app = FastAPI(title="my_pygeoapi", root_path="", debug=True)
+
+ # Set all CORS enabled origins
+ app.add_middleware(
+ CORSMiddleware,
+ allow_origins=["*"],
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+ )
+
+ @app.exception_handler(StarletteHTTPException)
+ async def custom_http_exception_handler(request, e):
+ return await http_exception_handler(request, e)
+
+ @app.exception_handler(RequestValidationError)
+ async def custom_validation_exception_handler(request, e):
+ return await request_validation_exception_handler(request, e)
+
+ # mount all pygeoapi endpoints to /oapi
+ app.mount(path="/oapi", app=pygeoapi_app)
+
+ return app
+
+app = create_app()
+
+if __name__ == "__main__":
+ uvicorn.run(app, port=5000)
+
pygeoapi supports multilinguality at three levels:
+Note
+Error messages are not translated, to facilitate copy-paste of the error into +stackoverflow and +GitHub issues.
+Language negotiation is triggered by the HTTP Accept-Language
header as sent by the client, and can always be overridden with the ?lang=fr
url parameter.
In the pygeoapi configuration you can indicate the languages supported by the instance. The first language is the default language. For most of the textual configuration properties you can provide a translation in alternative languages.
+1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 |
|
Most of the translatable text strings exist within the Jinja2 HTML templates. Text strings to be translated are placed in a trans
tag, as follows:
1 |
|
Babel provides a utility which extracts all keys to be translated from the templates into a single .pot
file.
pybabel extract -F babel-mapping.ini -o locale/messages.pot ./
+
The resulting .pot
file is used to create or update existing .po
files, which exist for each language, containing the actual translations.
pybabel init -d locale -l it -i locale/messages.pot
+
The .po
files are stored in pygeoapi's source code repository on GitHub. You can create a Pull Request to add or update your favourite languages. .po
files can also be added to translation software such as transifex.com.
Edit a .po
file
Open a .po
file from the locale folder in a text editor. Edit some values. Save the file and restart the service. Verify that the updated content is available. You can also try to add a new key to a template and translate it via the .po
mechanism.
pygeoapi includes a meachanism to influence the API responses based on the requested language. If your service operates with multilingual requirements, it may make sense to add textual columns in multiple languages. For example, in the pygeoapi configuration you can then indicate which column should be used as the title field, for which language.
+Publish a multilingual dataset
+For this workshop we have prepared a multilingual dataset of free wifi hotspots in Florence
(workshop/exercises/data/free-wifi-florence.csv
). Add the dataset to the pygeoapi configuration using the CSV provider. Add a title-field configuration with for each translated column the relevant language.
1 +2 +3 +4 +5 +6 |
|
Test the configuration by navigating to the items page of the collection and switching the language by appending ?lang=it
, ?lang=de
to the URL.
Congratulations! You've customized pygeoapi to support multiple languages.
+ + + + + + + + + + + + + + + + +In this section, we will discuss more advanced pygeoapi topics primarily +focused on extending pygeoapi via custom development and deployment.
+ + + + + + + + + + + + + + + + + +INSPIRE is a European directive on data sharing in the environmental domain. EU member states +have invested almost 20 years of effort to harmonize data in the environmental domain and publish it using OGC standards. +The directive is at the end of its lifetime, but the expectation is that conventions from the INSPIRE directive will be adopted +by upcoming directives, such as green deal and open data directives.
+In the past 20 years, the IT landscape has changed considerably. INSPIRE has followed these developments by adopting a +series of Good Practices which supersede the original +Technical Guidelines.
+Some of the recent and upcoming good practices focus on the developments in the OGC API domain. +One good practice has already been adopted on providing +download services using OGC API - Features +and others are in preparation, such as the +discovery service using OGC API - Records. +These developments make pygeoapi an interesting option +for providing INSPIRE services.
+INSPIRE services are typically categorized in view services, download services and discovery services. +Download services are further devided in Vector sources, Coverage sources and Sensor sources. +The OGC API initiative provides the related APIs for each service. +The table below highlights for each service type the Technical Guidenace +recommendation and the relevant Good Practices.
+Service type | +TG | +OGC API | +Good practice status | +
---|---|---|---|
Discovery service | +CSW | +OGC API - Records | +In preparation | +
View service | +WM(T)S | +OGC API - Maps / OGC API - Tiles | +Not scheduled In preparation |
+
Download service - Vector | +WFS | +OGC API - Features | +Adopted | +
Download service - Coverage | +WCS | +OGC API - Coverages / STAC | +Not scheduled In preparation |
+
Download service - Sensor | +SOS | +OGC API - EDR / Sensorthings API 1 | +Not scheduled Adopted |
+
Note
+When adopting Good Practices, consider that the documentation and tools for validation are still limited. +Also the INSPIRE GeoPortal may not be ready to harvest records from an OGC API - Records endpoint yet.
+Publish metadata documents as an INSPIRE discovery service
+In this exercise we will import a folder of metadata documents into a TinyDB database and configure the database as an OGC API - Records endpoint.
+Download the zipfile 'inspire-records.zip' from the repository. Expand the zipfile. The /tests
folder contains a script
+load_tinydb_records.py. The script has 2 parameters:
python3 load_tinydb_records.py <path/to/xml-files> <output.db>
+
Now configure TinyDB as a provider for OGC API - Records. Restart the service and verify the result. Verify also the XML output of some of the records.
+Most of the INSPIRE data models have a hierarchical structure, which is not common in the GeoJSON oriented OGC API community. +In theory it is possible to provide hierarchical GML from an OGC API endpoint, but there are not many experiences yet currently. +Two initiatives may bring improvement to this aspect:
+A typical use case in INSPIRE is the option to extend an INSPIRE codelist to match a local requirement. For this use case the +extended codelist has to be published in a registry. OGC API - Common provides mechanisms to publish lists of concepts as items +in collections. pygeoapi also provides a mechanism to advertise the concepts using the SKOS ontology via its JSON-LD +encoding. In the coincidence that a concept has a geometry property, the codelist can even be published as OGC API - Features +(on a map).
+Publish a codelist via OGC API
+A German Soiltype codelist has been made available in CSV format in workshop/exercises/data/bodenart.en.csv
. Use the CSV provider to publish this dataset in pygeoapi. Which URL would you use to reference a concept in the published list?
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 |
|
Congratulations! You have worked with pygeoapi for INSPIRE compliance
+ + + + + + + + + + + + + + + + + +Security in general is a broad and complex topic, affecting the entire development lifecycle. +It is recommended to follow security best practices during all development phases like design, coding and deployment. +In this workshop we will focus only on API security and access control, rather than the full range of application security topics.
+Application Security
+The Open Web Application Security Project (OWASP) Top Ten document is a very good tool to ensure the bare minimum against the security risks and manage critical treats that are most likely affecting your code.
+API Security is the whole process to protect APIs from attacks. It is part of the more general security guidelines that are being treated in the OWASP Top Ten document. So those recommendations still apply.
+Access control is another fundamental part of the Open Web Application Security Project and addresses the Identity and Access Management (IAM) of an API. +IAM consists of two different parts of a security flow:
+These parts are usually managed by dedicated infrastructures and solutions which usually provide most of the security requirements out-of-the-box.
+OpenAPI Security Specification
+The OpenAPI specification has very well-defined elements for developers and adopters. The most relevant are: + - Security Scheme Object defines the security schemes that can be used by the operations. Supported schemes are HTTP Authentication, an API Key, OAuth2's flows and OpenID Connect. + - Security Requirement Object defines the list of required security schemes to execute an operation.
+This section touches on 3 aspects of the Semantic Web:
+ +Search engines use technology similar to the Semantic Web to facilitate capturing structured data (aka rich snippets) from web pages.
+pygeoapi supports this use case via embedding a schema.org
JSON-LD snippet in the HTML encoding,
Tip
+The schema.org
ontology is not a formal Semantic Web ontology, it is therefore a bit disconnected from the rest of the Semantic Web
Tip
+See more information at Search Engine Optimization
+OGC API - Common adopted a number of W3C conventions, which bring OGC APIs closer to the standards of Semantic Web, +compared to first generation OGC Web Service (OWS) standards.
+Currently, pygeaopi does not aim to be a full implementation of Semantic Web, however it is possible to advertise +some aspects of the Semantic Web so the data can be traversed by Semantic Web aware clients.
+Use a SPARQL client to query pygeoapi
+SPARQL is commonly known as the query language to query triple stores. +However you can also use SPARQL to query graphs of linked web resources. The SPARQL client traverses links between +the resources to locate the requested triples. Jena ARQ is a command +line SPARQL client which is able to run such queries. Jena is quite difficult to set up, although there is a +Docker image available. As an alternative we will use a web-based implementation +of the ARQ engine. Navigate to https://demos.isl.ics.forth.gr/sparql-ld-endpoint +and replace the query in the textbox with:
+1 +2 +3 +4 +5 +6 +7 |
|
A query to an item returns the item with its geometry:
+1 +2 +3 +4 +5 |
|
Notice that the SPARQL client fails if you hardcode the HTML format.
+1 +2 +3 +4 +5 |
|
JSON-LD as expected by search engines has some challenges for semantic web tools. So how does it work if the format is not hardcoded?
+The SPARQL engine negotiates with the endpoint to evaluate which (RDF) encodings are available, and based on the content negotiation
+it requests the JSON_LD
encoding via f=jsonld
.
pygeoapi adopted conventions of the JSON-LD community to annotate JSON as RDF. For features, each property (column in a source table) +is annotated by a semantic concept. The related configuration to apply the annotations is managed in the context element of a resource definition
+Tip
+Read more in the pygeoapi documentation.
+1 +2 +3 +4 +5 +6 +7 +8 +9 |
|
Spatial data engineers are generally challenged when importing and visualizing fragments of the semantic web. The number of spatial +clients currently supporting SQARQL interaction is limited and requires expert knowledge to use. +A group within the pygeoapi community aims to facilitate semantic web access for spatial data engineers by introducing pygeoapi as a proxy +between the typical GIS clients and the semantic web.
+A new feature is being prepared which introduces a SPARQL provider to pygeoapi. +The provider enables to browse the results of a SPARQL query as an OGC API - Features collection.
+Congratulations! You can now configure pygeoapi configurations with linked data concepts.
+ + + + + + + + + + + + + + + + +OGC API - Features adopted the Spatial Data on the Web Best Practice 2: Make your spatial data indexable by search engines with the recommendation to include HTML as an output format of any OGC API. It means that users can navigate an OGC API from within their browser and Search Engines are able to crawl the content.
+An aspect to consider is that, since the API becomes a webpage, common practices for web architecture and development become relevant:
+Tip
+Notice that the pygeoapi configuration also has an option to disable HTML output. In that scenario, only the JSON output is available.
+On the Web, websites are typically visited by web crawlers of popular search engines. Crawlers +are automated processes which aid in building the index of the search engine. Crawlers follow links on the Web to identify new or updated +content. Cross linking your API to other resources therefore increases the visibility (and ranking) of your API.
+The British Geo6 wrote an extensive best practice on SEO for data publishers which offers a good overview of SEO in the scope of data publications.
+This paragraph introduces you to some mechanisms which facilitate or block web crawlers to index your content.
+If you are not interested in having your content indexed by search engines, you can provide a robots.txt +file at the root of your website, specifying which folders should not be indexed. More drastically is the option to block access for crawlers or bots to your content +by filtering traffic to the website based on the HTTP User-Agent header. Such a rule can +be added to a firewall or web server configuration.
+A robots.txt
file can also include a link to a Sitemap. Many search engines provide the option to submit a sitemap
+in order to speed up crawling and indexing. pygeoapi does not provide a sitemap of its content, but you can create your own sitemap (publish as /sitemap.xml
),
+specifying URLs of your desired content to be indexed.
Search engines provide tooling to evaluate the search behaviour of your website. These tools can provide valuable insight in the findability of your website +and content (e.g. keywords used to locate your website).
+Search engines cooperate in the Schema.org initiative. Schema.org enables you to annotate your website using the schema.org
vocabulaire, in
+order for search engines to index the content in a structured manner. Google was the first to employ these annotations to provide a dedicated search engine for datasets. pygeoapi adds schema.org/Dataset
annotations to collection pages, so collections are automagically included in Google's dataset search.
Evaluate the schema.org annotations in collections
+Google provides a tool to evaluate Schema.org
annotation in websites. Try evaluating a collection endpoint of pygeoapi
+in the tool. If you run pygeoapi locally (not accessible to google), you can copy the source of a page as HTML into the <code>
tab, otherwise you can paste the URL of the page in the URL
tab.
Note
+A similar tool is made available by Yandex (note that registration is required).
+pygeoapi adopted the Jinja2 templating mechanism to style HTML output. Each element visualized on the HTML output is
+customizable by overriding the relevant template. Templates are located in the pygeoapi/templates
folder.
+It is possible to override any template by copying it into a separate folder and adjust it to your needs. In the pygeoapi
+configuration you can then indicate the path to the override folder. Notice that for files which are not placed
+in the override folder, the original file is used.
Caution
+For any customization, mind that with a new version of pygeoapi changes on the default templates are not automatically +available on the overriden files. Upgrades need to be carefully tested and validated.
+Jinja2 is a common templating concept in the Python community. With a minimal background
+in HTML you will be able to make minor but meaningful customizations. At the core of pygeoapi's template setup is the
+_base.html
template, which defines the
+header and footer of the page. The fragment below defines the footer of the page, notice the parameters in curly braces,
+which are replaced by dynamic content.
1 +2 +3 +4 +5 +6 |
|
Customizing an HTML page
+Copy _base.html
to a separate folder. Adjust some elements on that page (e.g. logo image). Then, include a reference to the new folder in
+the pygeoapi configuration. Restart the service. Verify the result.
From the customized HTML template you can reference a new stylesheet file with customizations or directly add your customizations to /static/css/default.css.
+Congratulations! You've added a custom look and feel to your pygeoapi deployment.
+ + + + + + + + + + + + + + + + +