def test_render(self): req = self.mock(WMSMapRequest) ex_handler = self.mock(ExceptionHandler) req_ex = RequestError("the exception message", request=req) self.expect(req.exception_handler).result(ex_handler) self.expect(ex_handler.render(req_ex)) self.replay() req_ex.render()
def test_exception(self): self.req.set("exceptions", "inimage") self.req.set("transparent", "true") req = WMSMapRequest(self.req) req_ex = RequestError("the exception message", request=req) response = req_ex.render() assert response.content_type == "image/png" data = StringIO(response.data) assert is_png(data) img = Image.open(data) assert img.size == (150, 100)
def test_exception(self): self.req["exceptions"] = "blank" req = WMSMapRequest(self.req) req_ex = RequestError("the exception message", request=req) response = req_ex.render() assert response.content_type == "image/png" data = StringIO(response.data) assert is_png(data) img = Image.open(data) assert img.size == (150, 100) eq_(img.getpixel((0, 0)), 0) # pallete image eq_(img.getpalette()[0:3], [255, 255, 255])
def test_exception_w_transparent(self): self.req.set("exceptions", "inimage") self.req.set("transparent", "true") req = WMSMapRequest(self.req) req_ex = RequestError("the exception message", request=req) response = req_ex.render() assert response.content_type == "image/png" data = StringIO(response.data) assert is_png(data) img = Image.open(data) assert img.size == (150, 100) eq_(sorted([x for x in img.histogram() if x > 25]), [377, 14623]) img = img.convert("RGBA") eq_(img.getpixel((0, 0))[3], 0)
def test_exception_w_transparent(self): self.req.set("exceptions", "blank") self.req.set("transparent", "true") req = WMSMapRequest(self.req) req_ex = RequestError("the exception message", request=req) response = req_ex.render() assert response.content_type == "image/png" data = StringIO(response.data) assert is_png(data) img = Image.open(data) assert img.size == (150, 100) assert img.mode == "P" img = img.convert("RGBA") eq_(img.getpixel((0, 0))[3], 0)
def test_render(self): req = self.mock(WMSMapRequest) req_ex = RequestError("the exception message", request=req) ex_handler = WMS100ExceptionHandler() self.expect(req.exception_handler).result(ex_handler) self.replay() response = req_ex.render() assert response.content_type == "text/xml" expected_resp = """ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <WMTException version="1.0.0"> the exception message </WMTException> """ assert expected_resp.strip() == response.data
def check_map_request(self, request): if self.max_output_pixels and \ (request.params.size[0] * request.params.size[1]) > self.max_output_pixels: request.prevent_image_exception = True raise RequestError("image size too large", request=request) self.validate_layers(request) request.validate_format(self.image_formats) request.validate_srs(self.srs)
def test_render(self): req = self.mock(WMSMapRequest) req_ex = RequestError("the exception message", request=req) ex_handler = WMS110ExceptionHandler() self.expect(req.exception_handler).result(ex_handler) self.replay() response = req_ex.render() assert response.content_type == "application/vnd.ogc.se_xml" expected_resp = """ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE ServiceExceptionReport SYSTEM "http://schemas.opengis.net/wms/1.1.0/exception_1_1_0.dtd"> <ServiceExceptionReport version="1.1.0"> <ServiceException>the exception message</ServiceException> </ServiceExceptionReport> """ assert expected_resp.strip() == response.data assert validate_with_dtd(response.data, "wms/1.1.0/exception_1_1_0.dtd")
def validate_styles(self): if 'styles' in self.params: styles = self.params['styles'] if not set(styles.split(',')).issubset( set(['default', '', 'inspire_common:DEFAULT'])): raise RequestError('unsupported styles: ' + self.params['styles'], code='StyleNotDefined', request=self)
def authorized_demo(self, environ): if 'mapproxy.authorize' in environ: result = environ['mapproxy.authorize']('demo', [], environ=environ) if result['authorized'] == 'unauthenticated': raise RequestError('unauthorized', status=401) if result['authorized'] == 'full': return True return False return True
def check_request_dimensions(self, tile_layer, request): # check that unknown dimension for this layer are set to default if request.dimensions: for dimension, value in iteritems(request.dimensions): dimension = dimension.lower() if dimension not in tile_layer.dimensions and value != 'default': raise RequestError('unknown dimension: ' + str(dimension), code='InvalidParameterValue', request=request)
def layer(self, tile_request): if self.use_dimension_layers: internal_layer = self._internal_dimension_layer(tile_request) else: internal_layer = self._internal_layer(tile_request) if internal_layer is None: raise RequestError('unknown layer: ' + tile_request.layer, request=tile_request) return internal_layer
def authorized_tile_layers(self, env): if 'mapproxy.authorize' in env: result = env['mapproxy.authorize']('tms', [l for l in self.layers], environ=env) if result['authorized'] == 'unauthenticated': raise RequestError('unauthorized', status=401) if result['authorized'] == 'full': return self.layers if result['authorized'] == 'none': raise RequestError('forbidden', status=403) allowed_layers = odict() for layer in self.layers.itervalues(): if result['layers'].get(layer.name, {}).get('tile', False) == True: allowed_layers[layer.name] = layer return allowed_layers else: return self.layers
def test_render(self): req = self.mock(WMSMapRequest) req_ex = RequestError('the exception message', request=req) ex_handler = WMS110ExceptionHandler() self.expect(req.exception_handler).result(ex_handler) self.replay() response = req_ex.render() assert response.content_type == 'application/vnd.ogc.se_xml' expected_resp = b""" <?xml version="1.0"?> <!DOCTYPE ServiceExceptionReport SYSTEM "http://schemas.opengis.net/wms/1.1.0/exception_1_1_0.dtd"> <ServiceExceptionReport version="1.1.0"> <ServiceException>the exception message</ServiceException> </ServiceExceptionReport> """ assert expected_resp.strip() == response.data assert validate_with_dtd(response.data, 'wms/1.1.0/exception_1_1_0.dtd')
def _render_layer(self, layer): try: layer_img = layer.get_map(self.query) if layer_img is not None: layer_img.opacity = layer.opacity return layer, layer_img except SourceError: raise except MapBBOXError: raise RequestError('Request too large or invalid BBOX.', request=self.request) except MapError as e: raise RequestError('Invalid request: %s' % e.args[0], request=self.request) except TransformationError: raise RequestError('Could not transform BBOX: Invalid result.', request=self.request) except BlankImage: return layer, None
def _render_raise_exceptions(self, async_pool, render_layers, layer_merger): # call _render_layer, raise all exceptions try: for layer, layer_img in async_pool.imap(self._render_layer, render_layers): if layer_img is not None: layer_merger.add(layer_img, layer=layer) except SourceError, ex: raise RequestError(ex.args[0], request=self.request)
def wmts_request(req, validate=True): req_type = _parse_request_type(req) req_class = request_mapping.get(req_type, None) if req_class is None: # use map request to get an exception handler for the requested version dummy_req = request_mapping['tile'](param=req.args, url=req.base_url, validate=False) raise RequestError("unknown WMTS request type '%s'" % req_type, request=dummy_req) return req_class(param=req.args, url=req.base_url, validate=True, http=req)
def authorize_tile_layer(self, tile_layer, request): if 'mapproxy.authorize' in request.http.environ: query_extent = tile_layer.grid.srs.srs_code, tile_layer.tile_bbox(request) result = request.http.environ['mapproxy.authorize']('wmts', [tile_layer.name], query_extent=query_extent, environ=request.http.environ) if result['authorized'] == 'unauthenticated': raise RequestError('unauthorized', status=401) if result['authorized'] == 'full': return if result['authorized'] == 'partial': if result['layers'].get(tile_layer.name, {}).get('tile', False) == True: limited_to = result['layers'][tile_layer.name].get('limited_to') if not limited_to: limited_to = result.get('limited_to') if limited_to: return load_limited_to(limited_to) else: return None raise RequestError('forbidden', status=403)
def layer(self, tile_request): if self.use_dimension_layers: internal_layer = self._internal_dimension_layer(tile_request) else: internal_layer = self._internal_layer(tile_request) if internal_layer is None: raise RequestError('unknown layer: ' + tile_request.layer, request=tile_request) self.authorize_tile_layer(internal_layer.name, tile_request.http.environ) return internal_layer
def check_request(self, request, info_formats=None): request.make_request() if request.layer not in self.layers: raise RequestError('unknown layer: ' + str(request.layer), code='InvalidParameterValue', request=request) if request.tilematrixset not in self.layers[request.layer]: raise RequestError('unknown tilematrixset: ' + str(request.tilematrixset), code='InvalidParameterValue', request=request) if info_formats is not None: if '/' in request.infoformat: # mimetype if request.infoformat not in self.info_formats.values(): raise RequestError('unknown infoformat: ' + str(request.infoformat), code='InvalidParameterValue', request=request) else: # RESTful suffix if request.infoformat not in self.info_formats: raise RequestError('unknown infoformat: ' + str(request.infoformat), code='InvalidParameterValue', request=request) # set mimetype as infoformat request.infoformat = self.info_formats[request.infoformat]
def authorized_tile_layers(self, env): if 'mapproxy.authorize' in env: result = env['mapproxy.authorize']('wmts', [l for l in self.layers], query_extent=None, environ=env) if result['authorized'] == 'unauthenticated': raise RequestError('unauthorized', status=401) if result['authorized'] == 'full': return self.layers.values() if result['authorized'] == 'none': raise RequestError('forbidden', status=403) allowed_layers = [] for layer in itervalues(self.layers): if result['layers'].get(layer.name, {}).get('tile', False) == True: allowed_layers.append(layer) return allowed_layers else: return self.layers.values()
def test_render(self): req = self.mock(WMSMapRequest) req_ex = RequestError('the exception message', request=req) ex_handler = WMS130ExceptionHandler() self.expect(req.exception_handler).result(ex_handler) self.replay() response = req_ex.render() assert response.content_type == 'text/xml; charset=utf-8' expected_resp = b""" <?xml version="1.0"?> <ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wms/1.3.0/exceptions_1_3_0.xsd"> <ServiceException>the exception message</ServiceException> </ServiceExceptionReport> """ assert expected_resp.strip() == response.data assert validate_with_xsd(response.data, 'wms/1.3.0/exceptions_1_3_0.xsd')
def test_render_w_code(self): req = self.mock(WMSMapRequest) req_ex = RequestError("the exception message", code="InvalidFormat", request=req) ex_handler = WMS130ExceptionHandler() self.expect(req.exception_handler).result(ex_handler) self.replay() response = req_ex.render() assert response.content_type == "text/xml; charset=utf-8" expected_resp = """ <?xml version='1.0' encoding="UTF-8"?> <ServiceExceptionReport version="1.3.0" xmlns="http://www.opengis.net/ogc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/ogc http://schemas.opengis.net/wms/1.3.0/exceptions_1_3_0.xsd"> <ServiceException code="InvalidFormat">the exception message</ServiceException> </ServiceExceptionReport> """ assert expected_resp.strip() == response.data assert validate_with_xsd(response.data, "wms/1.3.0/exceptions_1_3_0.xsd")
def render(self, tile_request, use_profiles=False): if tile_request.format != self.format: raise RequestError( 'invalid format (%s). this tile set only supports (%s)' % (tile_request.format, self.format), request=tile_request, code='InvalidParameterValue') tile_coord = self._internal_tile_coord(tile_request, use_profiles=use_profiles) try: with self.tile_manager.session(): tile = self.tile_manager.load_tile_coord(tile_coord, with_metadata=True) if tile.source is None: return self.empty_response() format = None if self._mixed_format else tile_request.format return TileResponse(tile, format=format) except SourceError, e: raise RequestError(e.args[0], request=tile_request, internal=True)
def authorized_capability_layers(self, env): if 'mapproxy.authorize' in env: result = env['mapproxy.authorize']('wms.capabilities', self.layers.keys(), environ=env) if result['authorized'] == 'unauthenticated': raise RequestError('unauthorized', status=401) if result['authorized'] == 'full': return self.root_layer if result['authorized'] == 'partial': limited_to = result.get('limited_to') if limited_to: coverage = load_limited_to(limited_to) else: coverage = None return FilteredRootLayer(self.root_layer, result['layers'], coverage=coverage) raise RequestError('forbidden', status=403) else: return self.root_layer
def _internal_tile_coord(self, tile_request, use_profiles=False): tile_coord = self.grid.internal_tile_coord(tile_request.tile, use_profiles) if tile_coord is None: raise RequestError('The requested tile is outside the bounding box' ' of the tile map.', request=tile_request, code='TileOutOfRange') if tile_request.origin == 'nw' and self.grid.origin not in ('ul', 'nw'): tile_coord = self.grid.flip_tile_coord(tile_coord) elif tile_request.origin == 'sw' and self.grid.origin not in ('ll', 'sw', None): tile_coord = self.grid.flip_tile_coord(tile_coord) return tile_coord
def validate_param(self): missing_param = [] for param in self.expected_param: if self.non_strict and param in self.non_strict_params: continue if param not in self.params: missing_param.append(param) if missing_param: if 'format' in missing_param: self.params['format'] = 'image/png' raise RequestError('missing parameters ' + str(missing_param), request=self)
def validate_format(self, image_formats): format = self.params['format'] image_formats100 = [f.split('/', 1)[1].upper() for f in image_formats] if format in image_formats100: format = 'image/' + format.lower() self.params['format'] = format if format not in image_formats: format = self.params['format'] self.params['format'] = 'image/png' raise RequestError('unsupported image format: ' + format, code='InvalidFormat', request=self)
def filter_actual_layers(self, actual_layers, requested_layers, authorized_layers): if authorized_layers is not PERMIT_ALL_LAYERS: requested_layer_names = set(requested_layers) for layer_name in actual_layers.keys(): if layer_name not in authorized_layers: # check whether layer was requested explicit... if layer_name in requested_layer_names: raise RequestError('forbidden', status=403) # or implicit (part of group layer) else: del actual_layers[layer_name] elif authorized_layers[layer_name] is not None: limited_to = load_limited_to(authorized_layers[layer_name]) actual_layers[layer_name] = [LimitedLayer(lyr, limited_to) for lyr in actual_layers[layer_name]]
def wmts_request(req): if req.path.endswith(RESTFUL_CAPABILITIES_PATH): return WMTS100RestCapabilitiesRequest(req) match = tile_req_re.search(req.path) if not match: match = fi_req_re.search(req.path) if not match: raise RequestError('invalid request (%s)' % (req.path)) req_vars = match.groupdict() return WMTS100RestFeatureInfoRequest(req, req_vars, fi_url_converter) req_vars = match.groupdict() return WMTS100RestTileRequest(req, req_vars, url_converter)
def checked_dimensions(self, tile_request): dimensions = {} for dimension, values in self.dimensions.iteritems(): value = tile_request.dimensions.get(dimension) if value in values: dimensions[dimension] = value elif not value or value == 'default': dimensions[dimension] = values.default else: raise RequestError('invalid dimension value (%s=%s).' % (dimension, value), request=tile_request, code='InvalidParameterValue') return dimensions
def _render_raise_exceptions(self, async_pool, render_layers, layer_merger): # call _render_layer, raise all exceptions try: for layer_task in async_pool.imap(self._render_layer, render_layers, use_result_objects=True): if layer_task.exception is None: layer, layer_img = layer_task.result if layer_img is not None: layer_merger.add(layer_img, layer.coverage) else: ex = layer_task.exception async_pool.shutdown(True) reraise(ex) except SourceError as ex: raise RequestError(ex.args[0], request=self.request)
def legendgraphic(self, request): legends = [] self.check_legend_request(request) layer = request.params.layer if not self.layers[layer].has_legend: raise RequestError('layer %s has no legend graphic' % layer, request=request) legend = self.layers[layer].legend(request) [legends.append(i) for i in legend if i is not None] result = concat_legends(legends) if 'format' in request.params: mimetype = request.params.format_mime_type else: mimetype = 'image/png' img_opts = self.image_formats[request.params.format_mime_type] return Response(result.as_buffer(img_opts), mimetype=mimetype)
def make_tile_request(self): """ Initialize tile request. Sets ``tile`` and ``layer`` and ``format``. :raise RequestError: if the format does not match the URL template`` """ match = self.tile_req_re.search(self.http.path) if not match: raise RequestError('invalid request (%s)' % (self.http.path), request=self) req_vars = match.groupdict() self.layer = req_vars['Layer'] self.tile = int(req_vars['TileCol']), int(req_vars['TileRow']), int( req_vars['TileMatrix']) self.format = req_vars.get('Format') self.tilematrixset = req_vars['TileMatrixSet']
def featureinfo(self, request): infos = [] self.check_request(request, self.info_formats) tile_layer = self.layers[request.layer][request.tilematrixset] if not request.format: request.format = tile_layer.format bbox = tile_layer.grid.tile_bbox(request.tile) query = InfoQuery( bbox, tile_layer.grid.tile_size, tile_layer.grid.srs, request.pos, request.infoformat, ) self.check_request_dimensions(tile_layer, request) coverage = self.authorize_tile_layer(tile_layer, request, featureinfo=True) if not tile_layer.info_sources: raise RequestError('layer %s not queryable' % str(request.layer), code='OperationNotSupported', request=request) if coverage and not coverage.contains(query.coord, query.srs): infos = [] else: for source in tile_layer.info_sources: info = source.get_info(query) if info is None: continue infos.append(info) mimetype = request.infoformat if not infos: return Response('', mimetype=mimetype) resp, _ = combine_docs(infos) return Response(resp, mimetype=mimetype)
def _init_request(self): """ Initialize tile request. Sets ``tile`` and ``layer``. :raise RequestError: if the format is not ``/layer/z/x/y.format`` """ match = self.tile_req_re.search(self.http.path) if not match or match.group('begin') != self.req_prefix: raise RequestError('invalid request (%s)' % (self.http.path), request=self) self.layer = match.group('layer') self.dimensions = tuple() if match.group('layer_spec') is not None: self.dimensions = (match.group('layer_spec'), ) if not self.tile: self.tile = tuple([int(match.group(v)) for v in ['x', 'y', 'z']]) if not self.format: self.format = match.group('format')
def wms_request(req, validate=True, strict=True, versions=None): version = _parse_version(req) req_type = _parse_request_type(req) if versions and version not in versions: version_requests = None else: version_requests = request_mapping.get(version, None) if version_requests is None: negotiated_version = negotiate_version(version, supported_versions=versions) version_requests = request_mapping[negotiated_version] req_class = version_requests.get(req_type, None) if req_class is None: # use map request to get an exception handler for the requested version dummy_req = version_requests['map'](param=req.args, url=req.base_url, validate=False) raise RequestError("unknown WMS request type '%s'" % req_type, request=dummy_req) return req_class(param=req.args, url=req.base_url, validate=True, non_strict=not strict, http=req)
def authorized_layers(self, feature, layers, env, query_extent): if 'mapproxy.authorize' in env: result = env['mapproxy.authorize']('wms.' + feature, layers[:], environ=env, query_extent=query_extent) if result['authorized'] == 'unauthenticated': raise RequestError('unauthorized', status=401) if result['authorized'] == 'full': return PERMIT_ALL_LAYERS, None layers = {} if result['authorized'] == 'partial': for layer_name, permissions in iteritems(result['layers']): if permissions.get(feature, False) == True: layers[layer_name] = permissions.get('limited_to') limited_to = result.get('limited_to') if limited_to: coverage = load_limited_to(limited_to) else: coverage = None return layers, coverage else: return PERMIT_ALL_LAYERS, None