Implement configurable OGC schema locations (#347)

This commit is contained in:
Tom Kralidis
2020-01-20 14:56:04 -05:00
committed by GitHub
parent 33a59b87cc
commit d0d7ed48da
7 changed files with 135 additions and 12 deletions
+2 -1
View File
@@ -2,7 +2,7 @@
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2019 Tom Kralidis
# Copyright (c) 2020 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -42,6 +42,7 @@ server:
map:
url: https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png
attribution: '<a href="https://wikimediafoundation.org/wiki/Maps_Terms_of_Use">Wikimedia maps</a> | Map data &copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>'
# ogc_schemas_location: /opt/schemas.opengis.net
logging:
level: ERROR
+33 -5
View File
@@ -3,7 +3,7 @@
# Authors: Tom Kralidis <tomkralidis@gmail.com>
# Norman Barker <norman.barker@gmail.com>
#
# Copyright (c) 2018 Tom Kralidis
# Copyright (c) 2020 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -34,10 +34,10 @@ import os
import click
from flask import Flask, make_response, request
from flask import Flask, make_response, request, send_from_directory
from pygeoapi.api import API
from pygeoapi.util import yaml_load
from pygeoapi.util import get_mimetype, yaml_load
APP = Flask(__name__)
APP.url_map.strict_slashes = False
@@ -55,11 +55,39 @@ if CONFIG['server'].get('cors', False):
from flask_cors import CORS
CORS(APP)
APP.config['JSONIFY_PRETTYPRINT_REGULAR'] = \
CONFIG['server'].get('pretty_print', True)
APP.config['JSONIFY_PRETTYPRINT_REGULAR'] = CONFIG['server'].get(
'pretty_print', True)
api_ = API(CONFIG)
OGC_SCHEMAS_LOCATION = CONFIG['server'].get('ogc_schemas_location', None)
if (OGC_SCHEMAS_LOCATION is not None and
not OGC_SCHEMAS_LOCATION.startswith('http')):
# serve the OGC schemas locally
if not os.path.exists(OGC_SCHEMAS_LOCATION):
raise RuntimeError('OGC schemas misconfigured')
@APP.route('/schemas/<path:path>', methods=['GET'])
def schemas(path):
"""
Serve OGC schemas locally
:param path: path of the OGC schema document
:returns: HTTP response
"""
full_filepath = os.path.join(OGC_SCHEMAS_LOCATION, path)
dirname_ = os.path.dirname(full_filepath)
basename_ = os.path.basename(full_filepath)
# TODO: better sanitization?
path_ = dirname_.replace('..', '').replace('//', '')
return send_from_directory(path_, basename_,
mimetype=get_mimetype(basename_))
@APP.route('/')
def root():
+21 -3
View File
@@ -2,7 +2,7 @@
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2019 Tom Kralidis
# Copyright (c) 2020 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -29,6 +29,7 @@
from copy import deepcopy
import logging
import os
import click
import yaml
@@ -38,14 +39,27 @@ from pygeoapi.util import yaml_load
LOGGER = logging.getLogger(__name__)
# TODO: handle this better once schemas are public/final
# allow also for schema caching
OPENAPI_YAML = {
'oapif': 'http://schemas.opengis.net/ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml', # noqa
'oapip': 'https://raw.githubusercontent.com/opengeospatial/wps-rest-binding/master/core/openapi' # noqa
}
def get_ogc_schemas_location(server_config):
osl = server_config.get('ogc_schemas_location', None)
value = 'http://schemas.opengis.net'
if osl is not None:
if osl.startswith('http'):
value = osl
elif osl.startswith('/'):
value = os.path.join(server_config['url'], 'schemas')
return value
# TODO: remove this function once OGC API - Processing is final
def gen_media_type_object(media_type, api_type, path):
"""
@@ -101,6 +115,10 @@ def get_oas_30(cfg):
"""
paths = {}
osl = get_ogc_schemas_location(cfg['server'])
OPENAPI_YAML['oapif'] = os.path.join(osl, 'ogcapi/features/part1/1.0/openapi/ogcapi-features-1.yaml') # noqa
LOGGER.debug('setting up server info')
oas = {
'openapi': '3.0.2',
+8 -1
View File
@@ -4,6 +4,7 @@
#
#
# Copyright (c) 2019 Francesco Bartoli
# Copyright (c) 2020 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -46,7 +47,6 @@ app = Starlette()
app.mount('/static', StaticFiles(
directory='{}{}static'.format(os.path.dirname(os.path.realpath(__file__)),
os.sep)))
CONFIG = None
if 'PYGEOAPI_CONFIG' not in os.environ:
@@ -60,6 +60,13 @@ if CONFIG['server'].get('cors', False):
from starlette.middleware.cors import CORSMiddleware
app.add_middleware(CORSMiddleware, allow_origins=['*'])
OGC_SCHEMAS_LOCATION = CONFIG['server'].get('ogc_schemas_location', None)
if (OGC_SCHEMAS_LOCATION is not None and
not OGC_SCHEMAS_LOCATION.startswith('http')):
if not os.path.exists(OGC_SCHEMAS_LOCATION):
raise RuntimeError('OGC schemas misconfigured')
app.mount('/schemas', StaticFiles(directory=OGC_SCHEMAS_LOCATION))
api_ = API(CONFIG)
+17 -1
View File
@@ -2,7 +2,7 @@
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2019 Tom Kralidis
# Copyright (c) 2020 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -33,6 +33,7 @@ from datetime import date, datetime, time
from decimal import Decimal
import json
import logging
import mimetypes
import os
import re
from urllib.parse import urlparse
@@ -47,6 +48,9 @@ LOGGER = logging.getLogger(__name__)
TEMPLATES = '{}{}templates'.format(os.path.dirname(
os.path.realpath(__file__)), os.sep)
mimetypes.add_type('text/plain', '.yaml')
mimetypes.add_type('text/plain', '.yml')
def dategetter(date_property, collection):
"""
@@ -199,3 +203,15 @@ def render_j2_template(config, template, data):
template = env.get_template(template)
return template.render(config=config, data=data, version=__version__)
def get_mimetype(filename):
"""
helper function to return MIME type of a given file
:param filename: filename (with extension)
:returns: MIME type of given filename
"""
return mimetypes.guess_type(filename)[0]
+47
View File
@@ -0,0 +1,47 @@
# =================================================================
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2020 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# =================================================================
from pygeoapi.openapi import get_ogc_schemas_location
def test_str2bool():
default = {
'url': 'http://localhost:5000'
}
osl = get_ogc_schemas_location(default)
assert osl == 'http://schemas.opengis.net'
default['ogc_schemas_location'] = 'http://example.org/schemas'
osl = get_ogc_schemas_location(default)
assert osl == 'http://example.org/schemas'
default['ogc_schemas_location'] = '/opt/schemas.opengis.net'
osl = get_ogc_schemas_location(default)
+7 -1
View File
@@ -2,7 +2,7 @@
#
# Authors: Tom Kralidis <tomkralidis@gmail.com>
#
# Copyright (c) 2019 Tom Kralidis
# Copyright (c) 2020 Tom Kralidis
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
@@ -96,3 +96,9 @@ def test_json_serial():
with pytest.raises(TypeError):
util.json_serial('foo')
def test_mimetype():
assert util.get_mimetype('file.xml') == 'application/xml'
assert util.get_mimetype('file.yml') == 'text/plain'
assert util.get_mimetype('file.yaml') == 'text/plain'