From 3938420dc24dc744af4b9a49259e6407d9efebcc Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Sun, 12 Jul 2020 16:39:18 -0400 Subject: [PATCH] fix raw output for OAProc (#487) --- .../data-publishing/ogcapi-processes.rst | 6 ++++++ pygeoapi/api.py | 12 ++++++++---- pygeoapi/openapi.py | 18 ++++++++++++++++-- pygeoapi/util.py | 8 ++++++++ tests/test_api.py | 10 +++++++++- 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/docs/source/data-publishing/ogcapi-processes.rst b/docs/source/data-publishing/ogcapi-processes.rst index 053a12a..eb6184e 100644 --- a/docs/source/data-publishing/ogcapi-processes.rst +++ b/docs/source/data-publishing/ogcapi-processes.rst @@ -29,6 +29,12 @@ Processing examples - http://localhost:5000/processes - describe the ``hello-world`` process - http://localhost:5000/processes/hello-world +- show all jobs for the ``hello-world`` process + - http://localhost:5000/processes/hello-world/jobs +- execute a job for the ``hello-world`` process + - ``curl -X POST "http://localhost:5000/processes/hello-world/jobs" -H "Content-Type: application/json" -d "{\"inputs\":[{\"id\":\"name\",\"type\":\"text/plain\",\"value\":\"hi there2\"}]}"`` +- execute a job for the ``hello-world`` process with a raw response + - ``curl -X POST "http://localhost:5000/processes/hello-world/jobs?response=raw" -H "Content-Type: application/json" -d "{\"inputs\":[{\"id\":\"name\",\"type\":\"text/plain\",\"value\":\"hi there2\"}]}"`` .. todo:: add more examples once OAPIP implementation is complete diff --git a/pygeoapi/api.py b/pygeoapi/api.py index 90d5072..7d02077 100644 --- a/pygeoapi/api.py +++ b/pygeoapi/api.py @@ -48,7 +48,7 @@ from pygeoapi.provider.base import ( ProviderGenericError, ProviderConnectionError, ProviderNotFoundError, ProviderQueryError, ProviderItemNotFoundError) from pygeoapi.util import (dategetter, filter_dict_by_key_value, json_serial, - render_j2_template, str2bool, TEMPLATES) + render_j2_template, TEMPLATES, to_json) LOGGER = logging.getLogger(__name__) @@ -1320,13 +1320,17 @@ class API: try: outputs = p.execute(data_dict) m = p.metadata - if 'raw' in args and str2bool(args['raw']): + if 'response' in args and args['response'] == 'raw': headers_['Content-Type'] = \ m['outputs'][0]['output']['formats'][0]['mimeType'] - response = outputs + if 'json' in headers_['Content-Type']: + response = to_json(outputs) + else: + response = outputs else: response['outputs'] = outputs - return headers_, 201, json.dumps(response) + response = to_json(response) + return headers_, 200, response except Exception as err: exception = { 'code': 'InvalidParameterValue', diff --git a/pygeoapi/openapi.py b/pygeoapi/openapi.py index 8d4c8ce..4034a91 100644 --- a/pygeoapi/openapi.py +++ b/pygeoapi/openapi.py @@ -515,7 +515,7 @@ def get_oas_30(cfg): {'$ref': '#/components/parameters/f'} ], 'responses': { - '200': {'$ref': '#/components/responses/200'}, + '200': {'$ref': '{}/responses/ProcessCollection.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa 'default': {'$ref': '#/components/responses/default'} } } @@ -566,6 +566,7 @@ def get_oas_30(cfg): 'operationId': 'get{}Jobs'.format(k.capitalize()), 'responses': { '200': {'$ref': '#/components/responses/200'}, + '404': {'$ref': '{}/responses/NotFound.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa 'default': {'$ref': '#/components/responses/default'} } }, @@ -575,9 +576,22 @@ def get_oas_30(cfg): 'description': p.metadata['description'], 'tags': [k], 'operationId': 'execute{}Job'.format(k.capitalize()), - 'parameters': [], + 'parameters': [{ + 'name': 'response', + 'in': 'query', + 'description': 'Response type', + 'required': False, + 'schema': { + 'type': 'string', + 'enum': ['raw', 'document'], + 'default': 'document' + } + }], 'responses': { '200': {'$ref': '#/components/responses/200'}, + '201': {'$ref': '{}/responses/ExecuteAsync.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa + '404': {'$ref': '{}/responses/NotFound.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa + '500': {'$ref': '{}/responses/ServerError.yaml'.format(OPENAPI_YAML['oapip'])}, # noqa 'default': {'$ref': '#/components/responses/default'} }, 'requestBody': { diff --git a/pygeoapi/util.py b/pygeoapi/util.py index 5e92305..fc2c3de 100644 --- a/pygeoapi/util.py +++ b/pygeoapi/util.py @@ -29,6 +29,7 @@ """Generic util functions used in the code""" +import base64 from datetime import date, datetime, time from decimal import Decimal import json @@ -175,6 +176,13 @@ def json_serial(obj): if isinstance(obj, (datetime, date, time)): return obj.isoformat() + elif isinstance(obj, bytes): + try: + LOGGER.debug('Returning as UTF-8 decoded bytes') + return obj.decode('utf-8') + except UnicodeDecodeError: + LOGGER.debug('Returning as base64 encoded JSON object') + return base64.b64encode(obj) elif isinstance(obj, Decimal): return float(obj) diff --git a/tests/test_api.py b/tests/test_api.py index 22c3e7a..a2d4c34 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -2,7 +2,7 @@ # # Authors: Tom Kralidis # -# 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 @@ -643,6 +643,14 @@ def test_execute_process(config, api_): assert response['outputs'][0]['value'] == 'test' + args = {'response': 'raw'} + rsp_headers, code, response = api_.execute_process(req_headers, args, + json.dumps(req_body), + 'hello-world') + response = json.loads(response) + + assert response[0]['value'] == 'test' + api_.config['resources'] = {} req_headers = make_req_headers()