From 1715509f398cb35c95d376641b2f313083acce5c Mon Sep 17 00:00:00 2001 From: Tom Kralidis Date: Wed, 9 Jun 2021 14:33:09 -0400 Subject: [PATCH] add safeguard for formatting errors (#708) --- pygeoapi/api.py | 23 +++++++++++++++-------- pygeoapi/formatter/base.py | 10 ++++++++++ pygeoapi/formatter/csv_.py | 27 ++++++++++++++++----------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/pygeoapi/api.py b/pygeoapi/api.py index 4af8eff..f52ac1b 100644 --- a/pygeoapi/api.py +++ b/pygeoapi/api.py @@ -52,6 +52,7 @@ from shapely.errors import WKTReadingError from shapely.wkt import loads as shapely_loads from pygeoapi import __version__, l10n +from pygeoapi.formatter.base import FormatterSerializationError from pygeoapi.linked_data import (geojson2geojsonld, jsonldify, jsonldify_collection) from pygeoapi.log import setup_logger @@ -1413,14 +1414,20 @@ class API: formatter = load_plugin('formatter', {'name': 'CSV', 'geom': True}) - content = formatter.write( - data=content, - options={ - 'provider_def': get_provider_by_type( - collections[dataset]['providers'], - 'feature') - } - ) + try: + content = formatter.write( + data=content, + options={ + 'provider_def': get_provider_by_type( + collections[dataset]['providers'], + 'feature') + } + ) + except FormatterSerializationError as err: + LOGGER.error(err) + msg = 'Error serializing output' + return self.get_exception( + 500, headers, request.format, 'NoApplicableCode', msg) headers['Content-Type'] = '{}; charset={}'.format( formatter.mimetype, self.config['server']['encoding']) diff --git a/pygeoapi/formatter/base.py b/pygeoapi/formatter/base.py index 4a79de6..eb27464 100644 --- a/pygeoapi/formatter/base.py +++ b/pygeoapi/formatter/base.py @@ -65,3 +65,13 @@ class BaseFormatter: def __repr__(self): return ' {}'.format(self.name) + + +class FormatterGenericError(Exception): + """formatter generic error""" + pass + + +class FormatterSerializationError(FormatterGenericError): + """formatter serialization error""" + pass diff --git a/pygeoapi/formatter/csv_.py b/pygeoapi/formatter/csv_.py index 813d60b..18176b8 100644 --- a/pygeoapi/formatter/csv_.py +++ b/pygeoapi/formatter/csv_.py @@ -32,7 +32,7 @@ import logging import unicodecsv as csv -from pygeoapi.formatter.base import BaseFormatter +from pygeoapi.formatter.base import BaseFormatter, FormatterSerializationError LOGGER = logging.getLogger(__name__) @@ -85,17 +85,22 @@ class CSVFormatter(BaseFormatter): LOGGER.debug('CSV fields: {}'.format(fields)) - output = io.BytesIO() - writer = csv.DictWriter(output, fields) - writer.writeheader() + try: + output = io.BytesIO() + writer = csv.DictWriter(output, fields) + writer.writeheader() + + for feature in data['features']: + fp = feature['properties'] + if is_point: + fp['x'] = feature['geometry']['coordinates'][0] + fp['y'] = feature['geometry']['coordinates'][1] + LOGGER.debug(fp) + writer.writerow(fp) + except ValueError as err: + LOGGER.error(err) + raise FormatterSerializationError('Error writing CSV output') - for feature in data['features']: - fp = feature['properties'] - if is_point: - fp['x'] = feature['geometry']['coordinates'][0] - fp['y'] = feature['geometry']['coordinates'][1] - LOGGER.debug(fp) - writer.writerow(fp) return output.getvalue() def __repr__(self):