Skip to content

Commit f0cd31e

Browse files
committed
working on WPS output version selector
1 parent 3b36117 commit f0cd31e

File tree

1 file changed

+64
-14
lines changed

1 file changed

+64
-14
lines changed

twitcher/wps_restapi/utils.py

+64-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
from owslib.wps import ComplexData
22
from twitcher.utils import parse_request_query
33
from distutils.version import LooseVersion
4-
from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
4+
from pyramid.httpexceptions import HTTPSuccessful, HTTPError, HTTPInternalServerError
5+
from lxml import etree
6+
import requests
7+
8+
import logging
9+
LOGGER = logging.getLogger("TWITCHER")
10+
11+
VERSION_100 = '1.0.0'
12+
VERSION_200 = '2.0.0'
13+
CONTENT_TYPE_XML = 'application/xml'
14+
CONTENT_TYPE_JSON = 'application/json'
15+
OUTPUT_FORMAT_JSON = 'json'
16+
OUTPUT_FORMAT_XML = 'xml'
17+
OUTPUT_FORMATS = {
18+
VERSION_100: OUTPUT_FORMAT_XML,
19+
VERSION_200: OUTPUT_FORMAT_JSON,
20+
CONTENT_TYPE_XML: OUTPUT_FORMAT_XML,
21+
CONTENT_TYPE_JSON: OUTPUT_FORMAT_JSON,
22+
}
523

624

725
def wps_restapi_base_path(settings):
@@ -31,27 +49,59 @@ def jsonify(value):
3149
return value
3250

3351

34-
def get_wps_output_format(request):
52+
def get_wps_output_format(request, service_url=None):
3553
"""
3654
Get the preferred output format from WPS after checking various hints:
3755
- 'version' in query string
38-
- 'application/xml' or 'application/json' in accept headers
56+
- Content-Type in accept headers
57+
- GetCapabilities of the service
3958
40-
:param request:
41-
:return: 'json' or 'xml' (default: 'json' if no direct hint matched)
59+
:param request: request for which a response of WPS version-specific format must be generated.
60+
:param service_url: endpoint URL of the service to request 'GetCapabilities' if version not found by previous hints.
61+
:return: one of OUTPUT_FORMAT (default: 1.0.0 => 'xml' if no direct hint matched)
4262
"""
43-
# return specific type if requested by 'version'
63+
# return specific type if requested by 'version' query
4464
queries = parse_request_query(request)
4565
if 'version' in queries and len(queries['version']) > 0:
46-
max_version = max([LooseVersion(v) for v in queries['version']])
47-
if max_version >= LooseVersion('2.0.0'):
48-
return 'json'
49-
return 'xml'
50-
# version not specified as input, check accept headers
66+
out_version = min([LooseVersion(v) for v in queries['version']])
67+
out_format = OUTPUT_FORMATS.pop(out_version.version, None)
68+
return out_format or OUTPUT_FORMATS[VERSION_100]
69+
70+
# version not specified as query, check accept headers for specific and unique case
5171
accepts = [accept[0] for accept in request.accept.parsed]
52-
if 'application/xml' in accepts:
53-
return 'xml'
54-
return 'json'
72+
matched_accepts = list(set(OUTPUT_FORMATS) & set(accepts))
73+
if len(matched_accepts) == 1:
74+
return OUTPUT_FORMATS[matched_accepts[0]]
75+
76+
# version still ambiguous, verify service's GetCapabilities
77+
if service_url:
78+
getcap_url_100 = '{}?service=WPS&request=GetCapabilities'
79+
getcap_url_200 = '{}/processes'.format(service_url)
80+
getcap_resp_100 = requests.get(getcap_url_100)
81+
getcap_resp_200 = requests.get(getcap_url_200)
82+
83+
# analyse JSON response
84+
if isinstance(getcap_resp_200, HTTPSuccessful):
85+
try:
86+
# TODO: update get version if it is ever added to 'GetCapabilities' from WPS REST response
87+
# for now, suppose that a valid list in json body means that the service is WPS 2.0.0
88+
if isinstance(getcap_resp_200.json()['processes'], list):
89+
return OUTPUT_FORMATS[VERSION_200]
90+
except Exception as ex:
91+
LOGGER.error('Got exception in `get_wps_output_format` JSON parsing: {}'.format(repr(ex)))
92+
93+
# analyse XML response
94+
if isinstance(getcap_resp_100, HTTPSuccessful):
95+
try:
96+
# TODO XML implementation
97+
etree.fromstring(getcap_resp_100.content)
98+
return OUTPUT_FORMATS[VERSION_100]
99+
except Exception as ex:
100+
LOGGER.error('Got exception in `get_wps_output_format` XML parsing: {}'.format(repr(ex)))
101+
102+
# still not found, default to older version
103+
# for most probable format supported by services
104+
return OUTPUT_FORMATS[VERSION_100]
55105

56106

57107
def httpError(http_error_class, **body):

0 commit comments

Comments
 (0)