diff --git a/pygeoapi/flask_app.py b/pygeoapi/flask_app.py index d22e6b0..4bed078 100644 --- a/pygeoapi/flask_app.py +++ b/pygeoapi/flask_app.py @@ -45,8 +45,8 @@ APP = Flask(__name__) @APP.route('/') -def describe_collections(): - headers, status_code, content = views.describe_collections( +def root(): + headers, status_code, content = views.root( request.headers, request.args, APP.config['PYGEOAPI_BASEURL']) response = make_response(content, status_code) @@ -71,7 +71,7 @@ def api(): return response -@APP.route('/api/conformance') +@APP.route('/conformance') def api_conformance(): headers, status_code, content = views.api_conformance(request.headers, request.args) @@ -83,8 +83,20 @@ def api_conformance(): return response -@APP.route('//') -@APP.route('//') +@APP.route('/collections') +def describe_collections(): + headers, status_code, content = views.describe_collections( + request.headers, request.args) + + response = make_response(content, status_code) + if headers: + response.headers = headers + + return response + + +@APP.route('/collections//') +@APP.route('/collections//') def dataset(feature_collection, feature=None): if feature is None: headers, status_code, content = views.get_features( diff --git a/pygeoapi/openapi.py b/pygeoapi/openapi.py index 6147d13..277eb32 100644 --- a/pygeoapi/openapi.py +++ b/pygeoapi/openapi.py @@ -79,8 +79,8 @@ def get_oas_30(cfg): paths['/'] = { 'get': { - 'summary': 'Feature Collections', - 'descriptions': 'Feature Collections', + 'summary': 'API', + 'description': 'API', 'tags': ['server'], 'responses': { 200: { @@ -89,6 +89,7 @@ def get_oas_30(cfg): } } } + paths['/api'] = { 'get': { 'summary': 'This document', @@ -101,7 +102,8 @@ def get_oas_30(cfg): } } } - paths['/api/conformance'] = { + + paths['/conformance'] = { 'get': { 'summary': 'API conformance definition', 'description': 'API conformance definition', @@ -113,6 +115,20 @@ def get_oas_30(cfg): } } } + + paths['/collections'] = { + 'get': { + 'summary': 'Feature Collections', + 'descriptions': 'Feature Collections', + 'tags': ['server'], + 'responses': { + 200: { + 'description': 'successful operation' + } + } + } + } + oas['tags'].append({ 'name': 'server', 'description': cfg['metadata']['identification']['description'], @@ -134,7 +150,7 @@ def get_oas_30(cfg): tag['externalDocs']['url'] = link['url'] break oas['tags'].append(tag) - paths['/{}'.format(k)] = { + paths['/collections/{}'.format(k)] = { 'get': { 'summary': 'Get {} features'.format(v['title']), 'description': v['description'], diff --git a/pygeoapi/views.py b/pygeoapi/views.py index ff32a0a..0042fef 100644 --- a/pygeoapi/views.py +++ b/pygeoapi/views.py @@ -43,6 +43,69 @@ TEMPLATES = '{}{}templates'.format(os.path.dirname( os.path.realpath(__file__)), os.sep) +def root(headers, args, baseurl): + """ + Provide API + + :param headers: dict of HTTP headers + :param args: dict of HTTP request parameters + :param baseurl: baseurl of the server + + :returns: tuple of headers, status code, content + """ + + headers_ = { + 'Content-type': 'application/json' + } + + formats = ['json', 'html'] + + format_ = args.get('f') + if format_ is not None and format_ not in formats: + exception = { + 'code': 'InvalidParameterValue', + 'description': 'Invalid format' + } + LOGGER.error(exception) + return headers_, 400, json.dumps(exception) + + fcm = { + 'links': [], + } + + LOGGER.debug('Creating links') + fcm['links'] = [{ + 'rel': 'self', + 'type': 'application/json', + 'title': 'this document', + 'href': baseurl + }, { + 'rel': 'self', + 'type': 'text/html', + 'title': 'this document as HTML', + 'href': '{}?f=html'.format(baseurl) + }, { + 'rel': 'self', + 'type': 'application/openapi+json;version=3.0', + 'title': 'the OpenAPI definition as JSON', + 'href': '{}api'.format(baseurl) + }, { + 'rel': 'self', + 'type': 'text/html', + 'title': 'the OpenAPI definition as HTML', + 'href': '{}?f=html'.format(baseurl) + } + ] + + if format_ == 'html': # render + headers_['Content-type'] = 'text/html' + content = _render_j2_template(settings, 'service.html', fcm) + + return headers_, 200, content + + return headers_, 200, json.dumps(fcm) + + def api(headers, args, openapi): """ Provide OpenAPI document @@ -87,13 +150,12 @@ def api_conformance(headers, args): return headers_, 200, json.dumps(conformance) -def describe_collections(headers, args, baseurl): +def describe_collections(headers, args): """ Provide feature collection metadata :param headers: dict of HTTP headers :param args: dict of HTTP request parameters - :param baseurl: baseurl of the server :returns: tuple of headers, status code, content """ @@ -114,34 +176,9 @@ def describe_collections(headers, args, baseurl): return headers_, 400, json.dumps(exception) fcm = { - 'links': [], 'collections': [] } - LOGGER.debug('Creating links') - fcm['links'] = [{ - 'rel': 'self', - 'type': 'application/json', - 'title': 'this document', - 'href': baseurl - }, { - 'rel': 'self', - 'type': 'text/html', - 'title': 'this document as HTML', - 'href': '{}?f=html'.format(baseurl) - }, { - 'rel': 'self', - 'type': 'application/openapi+json;version=3.0', - 'title': 'the OpenAPI definition as JSON', - 'href': '{}api'.format(baseurl) - }, { - 'rel': 'self', - 'type': 'text/html', - 'title': 'the OpenAPI definition as HTML', - 'href': '{}?f=html'.format(baseurl) - } - ] - LOGGER.debug('Creating collections') for k, v in settings['datasets'].items(): collection = {'links': [], 'crs': []}