Skip to content

Commit

Permalink
Fix complexdata decoding as invalid base64
Browse files Browse the repository at this point in the history
    Fix #31
  • Loading branch information
dmarteau committed Oct 25, 2022
1 parent 34f3c68 commit 9d63e07
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 34 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Changes


## Unreleased

* Fix invalid decoding of complex data as base64
- Fix https://github.com/3liz/py-qgis-wps/issues/31
* Fix mandatory SERVICE parameters for POST WPS requests
* Deprecate `host_proxy` in favor of `proxy_url` option
* Define explicit `HTTP\_PROXY` option
Expand Down
8 changes: 0 additions & 8 deletions pyqgiswps/app/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,6 @@ def __repr__(self) -> str:
def dumps( self ):
return json.dumps(self.json, allow_nan=False)

#
# Execute
#
async def execute(self, service: Service, uuid: UUID,
map_uri: Optional[str]=None) -> bytes:

return await service.execute(self.identifier, self, uuid, map_uri)


class WPSResponse:

Expand Down
17 changes: 1 addition & 16 deletions pyqgiswps/app/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
from pyqgiswps.exceptions import (
MissingParameterValue,
NoApplicableCode,
InvalidParameterValue,
UnknownProcessError
)
from pyqgiswps.inout.inputs import ComplexInput, LiteralInput, BoundingBoxInput
from pyqgiswps.executors.processingexecutor import ProcessingExecutor
Expand Down Expand Up @@ -62,10 +60,7 @@ def get_process(self, ident: str, map_uri: Optional[str]=None) -> WPSProcess:
return self.get_processes((ident,), map_uri=map_uri)[0]

def get_processes(self, idents: Iterable[str], map_uri: Optional[str]=None) -> Iterable[WPSProcess]:
try:
return self.executor.get_processes(idents, map_uri=map_uri)
except UnknownProcessError as exc:
raise InvalidParameterValue(f"Invalid process '{exc}'")
return self.executor.get_processes(idents, map_uri=map_uri)

def get_results(self, uuid: str) -> Any:
doc = self.executor.get_results(uuid)
Expand All @@ -89,16 +84,6 @@ def kill_job(self, uuid: str, pid: Optional[int] = None) -> bool:
"""
return self.executor.kill_job(uuid, pid)

async def execute(self, identifier: str, wps_request: WPSRequest, uuid: str,
map_uri: Optional[str]=None) -> bytes:
"""Parse and perform Execute WPS request call
:param identifier: process identifier string
:param wps_request: pyqgiswps.WPSRequest structure with parsed inputs, still in memory
:param uuid: string identifier of the request
"""
process = self.get_process(identifier, map_uri=map_uri)
return await self.execute_process(process, wps_request, uuid)

async def execute_process(self, process: WPSProcess, wps_request: WPSRequest, uuid: str) -> bytes:
"""Parse and perform Execute WPS request call
Expand Down
2 changes: 2 additions & 0 deletions pyqgiswps/executors/io/geometryio.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ def json_to_geometry( data: str ) -> Geometry:
data = data['geometry']
geom = ogr.CreateGeometryFromJson(json.dumps(data))
if geom:
# XXX There is no method for direct import
# from json
geom = QgsGeometry.fromWkt(geom.ExportToWkt())
if crs and crs.isValid():
geom = QgsReferencedGeometry(geom,crs)
Expand Down
25 changes: 16 additions & 9 deletions pyqgiswps/ogc/ows/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
AccessPolicy = TypeVar('AccessPolicy')
Service = TypeVar('Service')
WPSProcess = TypeVar('WPSProcess')
UUID = TypeVar('UUID')


LOGGER = logging.getLogger('SRVLOG')

Expand Down Expand Up @@ -64,6 +66,8 @@ def __init__(self, *args, **kwargs):
def conformance() -> str:
return OGC_CONFORMANCE_NS.OWS_WPS.value



@staticmethod
def parse_get_request(handler) -> WPSRequest:
""" HTTP GET request parser
Expand Down Expand Up @@ -478,11 +482,20 @@ def get_processes_for_request(self, service: Service, idents: Iterable[str],
try:
return service.get_processes(idents, map_uri)
except UnknownProcessError as exc:
raise InvalidParameterValue("Unknown process %s" % exc, "identifier") from None
raise InvalidParameterValue(f"Unknown process '{exc}'", "identifier") from None
except Exception as e:
LOGGER.critical("Exception:\n%s",traceback.format_exc())
raise NoApplicableCode(str(e), code=500) from None

async def execute(self, service: Service, uuid: UUID,
map_uri: Optional[str]=None) -> bytes:
try:
process = service.get_process(self.identifier, map_uri=map_uri)
except UnknownProcessError as exc:
raise InvalidParameterValue(f"Invalid process '{exc}'", "identifier") from None

return await service.execute_process(process, self, uuid)

#
# Describe
#
Expand Down Expand Up @@ -534,15 +547,9 @@ def _get_dataelement_value(value_el):

def _get_rawvalue_value(data, encoding=None):
"""Return real value of CDATA section"""

try:
if encoding is None or encoding == "":
return data
elif encoding == 'base64':
return base64.b64decode(data)
if encoding == 'base64':
return base64.b64decode(data)
except Exception:
return data
return data


def _get_reference_body(body_element):
Expand Down
50 changes: 50 additions & 0 deletions tests/unittests/processing/test_owsexecute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
Test Processing executor
"""
import pytest
from pyqgiswps.app import WPSProcess, Service
from pyqgiswps.tests import HTTPTestCase
from pyqgiswps.executors.processfactory import get_process_factory

# XXX With EPSG:4326 axes *MUST* be inverted
INPUTGEOMETRY_EXECUTE_POST="""<?xml version="1.0" encoding="UTF-8"?>
<wps:Execute version="1.0.0" service="WPS"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.opengis.net/wps/1.0.0"
xmlns:wfs="http://www.opengis.net/wfs"
xmlns:wps="http://www.opengis.net/wps/1.0.0"
xmlns:ows="http://www.opengis.net/ows/1.1"
xmlns:gml="http://www.opengis.net/gml"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:wcs="http://www.opengis.net/wcs/1.1.1"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd">
<ows:Identifier>{PROVIDER}:testinputgeometry</ows:Identifier>
<wps:DataInputs>
<wps:Input>
<ows:Identifier>INPUT</ows:Identifier>
<wps:Data>
<wps:ComplexData mimeType="application/wkt" encoding="utf-8" schema=""><![CDATA[{DATA}]]></wps:ComplexData>
</wps:Data>
</wps:Input>
</wps:DataInputs>
</wps:Execute>
"""


class TestsInputGeometry(HTTPTestCase):

def get_processes(self):
return get_process_factory()._create_qgis_processes()

def test_input_geometry_execute_post(self):
""" Test processing executor 'Execute' request
"""
uri = ('/ows/?service=WPS&MAP=raster_layer')
body = INPUTGEOMETRY_EXECUTE_POST.format(
PROVIDER='pyqgiswps_test',
DATA='CRS=4326;POINT(-4 48)'
)
rv = self.client.post(body, path=uri)
assert rv.status_code == 200

2 changes: 1 addition & 1 deletion tests/unittests/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def test_complex_input_base64_value():
mimeType='application/json')))))
rv = get_inputs_from_xml(request_doc)
assert rv['json'][0]['mimeType'] == 'application/json'
json_data = json.loads(rv['json'][0]['data'].decode())
json_data = json.loads(rv['json'][0]['data'])
assert json_data['plot']['Version'] == '0.1'


Expand Down

0 comments on commit 9d63e07

Please sign in to comment.