From 44d347a09f2ec81103e6a08c5041f9cd1fb9eb97 Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Sun, 24 Mar 2019 15:20:05 -0400 Subject: [PATCH] support text/html encoding request in headers (#87) (#88) --- pygeoapi/api.py | 52 ++++++++++++++++++++++++++++++++++------------- tests/test_api.py | 44 ++++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 24 deletions(-) diff --git a/pygeoapi/api.py b/pygeoapi/api.py index a4bd353..ea0d3c2 100644 --- a/pygeoapi/api.py +++ b/pygeoapi/api.py @@ -49,6 +49,8 @@ HEADERS = { 'X-Powered-By': 'pygeoapi {}'.format(__version__) } +FORMATS = ['json', 'html'] + class API(object): """API object""" @@ -82,10 +84,9 @@ class API(object): headers_ = HEADERS.copy() - formats = ['json', 'html'] + format_ = check_format(args, headers) - format_ = args.get('f') - if format_ is not None and format_ not in formats: + if format_ is not None and format_ not in FORMATS: exception = { 'code': 'InvalidParameterValue', 'description': 'Invalid format' @@ -158,10 +159,9 @@ class API(object): headers_ = HEADERS.copy() - formats = ['json', 'html'] + format_ = check_format(args, headers) - format_ = args.get('f') - if format_ is not None and format_ not in formats: + if format_ is not None and format_ not in FORMATS: exception = { 'code': 'InvalidParameterValue', 'description': 'Invalid format' @@ -199,10 +199,9 @@ class API(object): headers_ = HEADERS.copy() - formats = ['json', 'html'] + format_ = check_format(args, headers) - format_ = args.get('f') - if format_ is not None and format_ not in formats: + if format_ is not None and format_ not in FORMATS: exception = { 'code': 'InvalidParameterValue', 'description': 'Invalid format' @@ -282,7 +281,7 @@ class API(object): properties = [] reserved_fieldnames = ['bbox', 'f', 'limit', 'startindex', 'resulttype', 'time'] - formats = ['json', 'html'] + formats = FORMATS formats.extend(f.lower() for f in PLUGINS['formatter'].keys()) if dataset not in self.config['datasets'].keys(): @@ -293,7 +292,8 @@ class API(object): LOGGER.error(exception) return headers_, 400, json.dumps(exception) - format_ = args.get('f') + format_ = check_format(args, headers) + if format_ is not None and format_ not in formats: exception = { 'code': 'InvalidParameterValue', @@ -482,10 +482,9 @@ class API(object): headers_ = HEADERS.copy() - formats = ['json', 'html'] + format_ = check_format(args, headers) - format_ = args.get('f') - if format_ is not None and format_ not in formats: + if format_ is not None and format_ not in FORMATS: exception = { 'code': 'InvalidParameterValue', 'description': 'Invalid format' @@ -633,6 +632,31 @@ class API(object): return headers_, 400, json.dumps(exception) +def check_format(args, headers): + """ + check format requested from arguments or headers + + :param args: dict of request keyword value pairs + :param headers: dict of request headers + + :returns: format value + """ + + format_ = args.get('f') + + if 'accept' in headers.keys(): + format_ = headers['accept'] + elif 'Accept' in headers.keys(): + format_ = headers['Accept'] + + if format_ == 'text/html': + format_ = 'html' + elif format_ == 'application/json': + format_ = 'json' + + return format_ + + def to_json(dict_): """ serialize dict to json diff --git a/tests/test_api.py b/tests/test_api.py index 844c660..e638a5b 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -33,7 +33,7 @@ import os import pytest import yaml -from pygeoapi.api import API +from pygeoapi.api import API, check_format def get_test_file_path(filename): @@ -69,7 +69,7 @@ def api_(config): return API(config) -def test_api(config, api_, openapi): +def test_api(config, api_, openapi, headers): assert api_.config == config assert isinstance(api_.config, dict) @@ -80,12 +80,12 @@ def test_api(config, api_, openapi): assert isinstance(root, dict) -def test_api_exception(config, api_): +def test_api_exception(config, api_, headers): headers_, code, response = api_.root(headers, {'f': 'foo'}) assert code == 400 -def test_root(config, api_): +def test_root(config, api_, headers): headers_, code, response = api_.root(headers, {}) root = json.loads(response) @@ -100,7 +100,7 @@ def test_root(config, api_): assert headers_['Content-Type'] == 'text/html' -def test_api_conformance(config, api_): +def test_api_conformance(config, api_, headers): headers_, code, response = api_.api_conformance(headers, {}) root = json.loads(response) @@ -115,7 +115,7 @@ def test_api_conformance(config, api_): assert headers_['Content-Type'] == 'text/html' -def test_describe_collections(config, api_): +def test_describe_collections(config, api_, headers): headers_, code, response = api_.describe_collections(headers, {'f': 'foo'}) assert code == 400 @@ -146,7 +146,7 @@ def test_describe_collections(config, api_): assert headers_['Content-Type'] == 'text/html' -def test_get_features(config, api_): +def test_get_features(config, api_, headers): headers_, code, response = api_.get_features(headers, {}, 'foo') features = json.loads(response) @@ -213,7 +213,7 @@ def test_get_features(config, api_): assert headers_['Content-Type'] == 'text/csv; charset=utf-8' -def test_get_feature(config, api_): +def test_get_feature(config, api_, headers): headers_, code, response = api_.get_feature( headers, {'f': 'foo'}, 'obs', '371') @@ -238,7 +238,7 @@ def test_get_feature(config, api_): assert features['properties']['stn_id'] == '35' -def test_describe_processes(config, api_): +def test_describe_processes(config, api_, headers): headers_, code, response = api_.describe_processes(headers, {}, 'foo') processes = json.loads(response) @@ -263,7 +263,7 @@ def test_describe_processes(config, api_): assert len(process['jobControlOptions']) == 1 -def test_execute_process(config, api_): +def test_execute_process(config, api_, headers): request = { 'inputs': [{ 'id': 'name', @@ -287,3 +287,27 @@ def test_execute_process(config, api_): response = json.loads(response) assert response['outputs'][0]['value'] == 'test' + + +def test_check_format(headers): + args = { + 'f': 'html' + } + + headers_ = headers.copy() + + assert check_format({}, headers_) is None + + assert check_format(args, headers_) == 'html' + + args['f'] = 'json' + assert check_format(args, headers_) == 'json' + + headers_['Accept'] = 'text/html' + assert check_format({}, headers_) == 'html' + + headers_['Accept'] = 'application/json' + assert check_format({}, headers_) == 'json' + + headers_['accept'] = 'text/html' + assert check_format({}, headers_) == 'html'