def _open_url(self, url_base, data=None, method='Get', cookies=None, username=None, password=None, timeout=30, headers=None): headers = headers if headers is not None else {} kwargs = dict(timeout=timeout) kwargs['auth'] = self.auth method = method.split("}")[-1] if method.lower() == 'post': try: _ = etree.fromstring(data) headers['Content-Type'] = 'text/xml' except (ParseError, UnicodeEncodeError): pass kwargs['data'] = data elif method.lower() == 'get': kwargs['params'] = data else: raise ValueError( "Unknown method ('%s'), expected 'get' or 'post'" % method) if cookies is not None: kwargs['cookies'] = cookies req = requests.request(method.upper(), url_base, headers=headers, **kwargs) if req.status_code in [400, 401]: raise ServiceException(req.text) if req.status_code in [404]: # add more if needed req.raise_for_status() if 'Content-Type' in req.headers and req.headers['Content-Type'] in [ 'text/xml', 'application/xml' ]: se_tree = etree.fromstring(req.content) serviceException = se_tree.find( '{http://www.opengis.net/ows}Exception') if serviceException is None: serviceException = se_tree.find('ServiceException') if serviceException is not None: raise ServiceException(str(serviceException.text).strip()) return ResponseWrapper(req)
def __init__(self, url, version='1.1.1', xml=None, username=None, password=None, parse_remote_metadata=False, headers=None, timeout=30, auth=None): """Initialize.""" if auth: if username: auth.username = username if password: auth.password = password self.url = url self.version = version self.timeout = timeout self.headers = headers self._capabilities = None self.auth = auth or Authentication(username, password) # Authentication handled by Reader reader = WMSCapabilitiesReader( self.version, url=self.url, headers=headers, auth=self.auth) if xml: # read from stored xml self._capabilities = reader.readString(xml) else: # read from server self._capabilities = reader.read(self.url, timeout=self.timeout) self.request = reader.request # avoid building capabilities metadata if the # response is a ServiceExceptionReport se = self._capabilities.find('ServiceException') if se is not None: err_message = str(se.text).strip() raise ServiceException(err_message) # build metadata objects self._buildMetadata(parse_remote_metadata)
def __init__(self, url, version=None, xml=None, username=None, password=None, parse_remote_metadata=False, headers=None, timeout=config_loader(dataset="WMS_request_timeout"), auth=None): """Initialize.""" if auth: if username: auth.username = username if password: auth.password = password self.url = url self.version = version self.timeout = timeout self.headers = headers self._capabilities = None self.auth = auth or Authentication(username, password) # Authentication handled by Reader reader = WMSCapabilitiesReader(self.version, url=self.url, headers=headers, auth=self.auth) if xml: # read from stored xml self._capabilities = reader.readString(xml) else: # read from server self._capabilities = reader.read(self.url, timeout=self.timeout) self.request = reader.request if not self.version: self.version = self._capabilities.attrib["version"] if self.version not in ["1.1.1", "1.3.0"]: self.version = "1.1.1" reader.version = self.version self.WMS_NAMESPACE = "{http://www.opengis.net/wms}" if self.version == "1.3.0" else "" self.OGC_NAMESPACE = "{http://www.opengis.net/ogc}" if self.version == "1.3.0" else "" # avoid building capabilities metadata if the # response is a ServiceExceptionReport se = self._capabilities.find('ServiceException') if se is not None: err_message = str(se.text).strip() raise ServiceException(err_message) # (mss) Store capabilities document. self.capabilities_document = reader.capabilities_document # (mss) # build metadata objects self._buildMetadata(parse_remote_metadata)
def Subgetmap_url(self, layers=None, styles=None, srs=None, bbox=None, format=None, size=None, time=None, transparent=False, bgcolor='#FFFFFF', exceptions='application/vnd.ogc.se_xml', method='Get', timeout=None, **kwargs): try: base_url = next((m.get('url') for m in self.getOperationByName('GetMap').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = {'version': self.version, 'request': 'GetMap'} request = self.__build_getmap_request(layers=layers, styles=styles, srs=srs, bbox=bbox, format=format, size=size, time=time, transparent=transparent, bgcolor=bgcolor, exceptions=exceptions, **kwargs) data = urlencode(request) ########## #Replace + with %20 ########## data = data.replace("+", "%20") request = bind_url(base_url) + data # GetMap validity u = openURL(base_url, data, method, username=self.username, password=self.password, timeout=timeout or self.timeout) # check for service exceptions, and return if u.info()['Content-Type'].split(';')[0] in [ 'application/vnd.ogc.se_xml' ]: se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = six.text_type( se_tree.find('ServiceException').text).strip() raise ServiceException(err_message) return request
def getcapabilities(self): """ Request and return capabilities document from the WMS as a file-like object. NOTE: this is effectively redundant now """ reader = WMSCapabilitiesReader(self.version, url=self.url, un=self.username, pw=self.password) u = self._open(reader.capabilities_url(self.url)) # check for service exceptions, and return if u.info().gettype() == 'application/vnd.ogc.se_xml': se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = str(se_tree.find('ServiceException').text).strip() raise ServiceException(err_message, se_xml) return u
def getcapabilities(self): """ Request and return capabilities document from the WMS as a file-like object. NOTE: this is effectively redundant now """ reader = WMSCapabilitiesReader(self.version, url=self.url, auth=self.auth) u = self._open(reader.capabilities_url(self.url)) # check for service exceptions, and return if u.info()['Content-Type'] == 'application/vnd.ogc.se_xml': se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = str( se_tree.find( f'{self.OGC_NAMESPACE}ServiceException').text).strip() raise ServiceException(err_message, se_xml) return u
def __init__(self, url, version=None, xml=None, username=None, password=None, parse_remote_metadata=False, timeout=30, headers=None): """initialize""" self.url = url self.username = username self.password = password self.version = version self.timeout = timeout self.headers = headers self._capabilities = None # Authentication handled by Reader # Check whether required parameters (service, version, request) exist. If not, the missing parameters will be added. reader = SubWMSCapabilitiesReader(self.version, url=self.url, un=self.username, pw=self.password, headers=headers) if xml: # read from stored xml self._capabilities = reader.readString(xml) else: # read from server self._capabilities = reader.read(self.url, timeout=self.timeout) self.request = reader.request # avoid building capabilities metadata if the # response is a ServiceExceptionReport if subcommon.WMSExceptionDetection(self._capabilities): raise ServiceException("ServiceException") # build metadata objects self._buildMetadata(parse_remote_metadata)
def __init__(self, url, credentials=Credentials(), cached_ows_services=None, logger=None, timeout=30): (username, password) = credentials.getFromUrl(url) if logger is not None: self.logger = logger else: self.logger = logging.getLogger("cswquerier") self.logger.addHandler(logging.NullHandler()) self.owsServices = cached_ows_services or CachedOwsServices( credentials=credentials, timeout=timeout) try: self.csw = CatalogueServiceWeb(url, username=username, password=password) except BaseException as ex: raise ServiceException(ex) self.mds_not_parsable = [] self.reset()
def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname='*', maxfeatures=None, srsname=None, outputFormat=None, method='Get', startindex=None, sortby=None): """Request and return feature data as a file-like object. Parameters ---------- typename : list List of typenames (string) filter : string XML-encoded OGC filter expression. bbox : tuple (left, bottom, right, top) in the feature type's coordinates. featureid : list List of unique feature ids (string) featureversion : string Default is most recent feature version. propertyname : list List of feature property names. '*' matches all. maxfeatures : int Maximum number of features to be returned. method : string Qualified name of the HTTP DCP method to use. srsname: string EPSG code to request the data in outputFormat: string (optional) Requested response format of the request. startindex: int (optional) Start position to return feature set (paging in combination with maxfeatures) sortby: list (optional) List of property names whose values should be used to order (upon presentation) the set of feature instances that satify the query. There are 3 different modes of use 1) typename and bbox (simple spatial query). It is assumed, that bbox coordinates are given *always* in the east,north order 2) typename and filter (more expressive) 3) featureid (direct access to known features) """ try: base_url = next((m.get('url') for m in self.getOperationByName('GetFeature').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = {'service': 'WFS', 'version': self.version, 'request': 'GetFeature'} if not isinstance(typename, list): typename = [typename] if srsname is not None: request['srsname'] = str(srsname) # Check, if desired SRS is supported by the service for each # typename. Warning will be thrown if that SRS is not allowed." for name in typename: _ = self.getSRS(srsname, name) # check featureid if featureid: request['featureid'] = ','.join(featureid) # bbox elif bbox and typename: request["bbox"] = self.getBBOXKVP(bbox, typename) # or filter elif filter and typename: request['filter'] = str(filter) assert len(typename) > 0 request['typename'] = ','.join(typename) if propertyname is not None: if not isinstance(propertyname, list): propertyname = [propertyname] request['propertyname'] = ','.join(propertyname) if sortby is not None: if not isinstance(sortby, list): sortby = [sortby] request['sortby'] = ','.join(sortby) if featureversion is not None: request['featureversion'] = str(featureversion) if maxfeatures is not None: request['maxfeatures'] = str(maxfeatures) if startindex is not None: request['startindex'] = str(startindex) if outputFormat is not None: request["outputFormat"] = outputFormat data = urlencode(request) log.debug("Making request: %s?%s" % (base_url, data)) u = openURL(base_url, data, method, timeout=self.timeout, auth=self.auth) # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k # is data. We'll check anything smaller. if 'Content-Length' in u.info(): length = int(u.info()['Content-Length']) have_read = False else: data = u.read() have_read = True length = len(data) if length < 32000: if not have_read: data = u.read() try: tree = etree.fromstring(data) except BaseException: # Not XML return self._makeStringIO(data) else: if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]: se = tree.find(nspath_eval('ServiceException', namespaces["ogc"])) raise ServiceException(str(se.text).strip()) else: return self._makeStringIO(data) else: if have_read: return self._makeStringIO(data) return u
def getfeatureinfo(self, layers=None, styles=None, srs=None, bbox=None, format=None, size=None, time=None, elevation=None, dimensions={}, transparent=False, bgcolor='#FFFFFF', exceptions='XML', query_layers=None, xy=None, info_format=None, feature_count=20, method='Get', timeout=None, **kwargs): try: base_url = next( (m.get('url') for m in self.getOperationByName('GetFeatureInfo').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url # GetMap-Request request = self.__build_getmap_request(layers=layers, styles=styles, srs=srs, bbox=bbox, dimensions=dimensions, elevation=elevation, format=format, size=size, time=time, transparent=transparent, bgcolor=bgcolor, exceptions=exceptions, kwargs=kwargs) # extend to GetFeatureInfo-Request request['request'] = 'GetFeatureInfo' if not query_layers: __str_query_layers = ','.join(layers) else: __str_query_layers = ','.join(query_layers) request['query_layers'] = __str_query_layers request['i'] = str(xy[0]) request['j'] = str(xy[1]) request['info_format'] = info_format request['feature_count'] = str(feature_count) data = urlencode(request) self.request = bind_url(base_url) + data u = openURL(base_url, data, method, username=self.username, password=self.password, timeout=timeout or self.timeout) # check for service exceptions, and return if u.info()['Content-Type'] == 'XML': se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = six.text_type( se_tree.find('ServiceException').text).strip() raise ServiceException(err_message) return u
def getmap(self, layers=None, styles=None, srs=None, bbox=None, format=None, size=None, time=None, elevation=None, dimensions={}, transparent=False, bgcolor='#FFFFFF', exceptions='XML', method='Get', timeout=None, **kwargs): """Request and return an image from the WMS as a file-like object. Parameters ---------- layers : list List of content layer names. styles : list Optional list of named styles, must be the same length as the layers list. srs : string A spatial reference system identifier. Note: this is an invalid query parameter key for 1.3.0 but is being retained for standardization with 1.1.1. Note: throws exception if the spatial ref is ESRI's "no reference" code (EPSG:0) bbox : tuple (left, bottom, right, top) in srs units (note, this order does not change depending on axis order of the crs). CRS:84: (long, lat) EPSG:4326: (lat, long) format : string Output image format such as 'image/jpeg'. size : tuple (width, height) in pixels. time : string or list or range Optional. Time value of the specified layer as ISO-8601 (per value) elevation : string or list or range Optional. Elevation value of the specified layer. dimensions: dict (dimension : string or list or range) Optional. Any other Dimension option, as specified in the GetCapabilities transparent : bool Optional. Transparent background if True. bgcolor : string Optional. Image background color. method : string Optional. HTTP DCP method name: Get or Post. **kwargs : extra arguments anything else e.g. vendor specific parameters Example ------- wms = WebMapService('http://webservices.nationalatlas.gov/wms/1million',\ version='1.3.0') img = wms.getmap(layers=['airports1m'],\ styles=['default'],\ srs='EPSG:4326',\ bbox=(-176.646, 17.7016, -64.8017, 71.2854),\ size=(300, 300),\ format='image/jpeg',\ transparent=True) out = open('example.jpg.jpg', 'wb') out.write(img.read()) out.close() """ try: base_url = next((m.get('url') for m in self.getOperationByName('GetMap').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = self.__build_getmap_request(layers=layers, styles=styles, srs=srs, bbox=bbox, dimensions=dimensions, elevation=elevation, format=format, size=size, time=time, transparent=transparent, bgcolor=bgcolor, exceptions=exceptions, **kwargs) data = urlencode(request) self.request = bind_url(base_url) + data u = openURL(base_url, data, method, username=self.username, password=self.password, timeout=timeout or self.timeout) # need to handle casing in the header keys headers = {} for k, v in six.iteritems(u.info()): headers[k.lower()] = v # handle the potential charset def if headers['content-type'].split(';')[0] in [ 'application/vnd.ogc.se_xml', 'text/xml' ]: se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = six.text_type( se_tree.find(nspath('ServiceException', OGC_NAMESPACE)).text).strip() raise ServiceException(err_message) return u
def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname=['*'], maxfeatures=None, srsname=None, outputFormat=None, method='Get', timeout=None): """Request and return feature data as a file-like object. Parameters ---------- typename : list List of typenames (string) filter : string XML-encoded OGC filter expression. bbox : tuple (left, bottom, right, top) in the feature type's coordinates. featureid : list List of unique feature ids (string) featureversion : string Default is most recent feature version. propertyname : list List of feature property names. '*' matches all. maxfeatures : int Maximum number of features to be returned. method : string Qualified name of the HTTP DCP method to use. srsname: string EPSG code to request the data in outputFormat: string (optional) Requested response format of the request. timeout : number A timeout value (in seconds) for the request. There are 3 different modes of use 1) typename and bbox (simple spatial query). It is assumed, that bbox coordinates are given *always* in the east,north order 2) typename and filter (more expressive) 3) featureid (direct access to known features) """ if timeout: to = timeout else: to = self.timeout try: base_url = next( (m.get('url') for m in self.getOperationByName('GetFeature').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = { 'service': 'WFS', 'version': self.version, 'request': 'GetFeature' } if not isinstance(typename, list): typename = [typename] if srsname is not None: # check, if desired SRS is supported by the service for this typename if typename is not None: # convert srsname string to Crs object found in GetCaps srsnameobj = self.getSRS(srsname, typename[0]) if srsnameobj is not None: request['srsname'] = srsnameobj.id else: options = ", ".join( map(lambda x: x.id, self.contents[typename[0]].crsOptions)) raise ServiceException( "SRSNAME %s not supported. Options: %s" % (srsname, options)) else: request['srsname'] = str(srsname) # check featureid if featureid: request['featureid'] = ','.join(featureid) # bbox elif bbox and typename: request["bbox"] = self.getBBOXKVP(bbox, typename) # or filter elif filter and typename: request['filter'] = str(filter) assert len(typename) > 0 request['typename'] = ','.join(typename) if propertyname is not None: if not isinstance(propertyname, list): propertyname = [propertyname] request['propertyname'] = ','.join(propertyname) if featureversion is not None: request['featureversion'] = str(featureversion) if maxfeatures is not None: request['maxfeatures'] = str(maxfeatures) if outputFormat is not None: request["outputFormat"] = outputFormat data = urlencode(request) log.debug("Making request: %s?%s" % (base_url, data)) u = openURL(base_url, data, method, timeout=to) # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k # is data. We'll check anything smaller. try: length = int(u.info()['Content-Length']) have_read = False except (KeyError, AttributeError): data = u.read() have_read = True length = len(data) if length < 32000: if not have_read: data = u.read() try: tree = etree.fromstring(data) except BaseException: # Not XML return StringIO(data) else: if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]: se = tree.find( nspath_eval('ServiceException', namespaces["ogc"])) raise ServiceException(str(se.text).strip()) else: return StringIO(data) else: if have_read: return StringIO(data) return u
def Subgetmap_url(self, layers=None, styles=None, srs=None, bbox=None, format=None, size=None, time=None, elevation=None, dimensions={}, transparent=False, bgcolor='#FFFFFF', exceptions='XML', method='Get', timeout=None, **kwargs): try: base_url = next((m.get('url') for m in self.getOperationByName('GetMap').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = self.__build_getmap_request(layers=layers, styles=styles, srs=srs, bbox=bbox, dimensions=dimensions, elevation=elevation, format=format, size=size, time=time, transparent=transparent, bgcolor=bgcolor, exceptions=exceptions, **kwargs) data = urlencode(request) data = data.replace("+", "%20") request = bind_url(base_url) + data u = openURL(base_url, data, method, username=self.username, password=self.password, timeout=timeout or self.timeout) # need to handle casing in the header keys headers = {} for k, v in six.iteritems(u.info()): headers[k.lower()] = v # handle the potential charset def if headers['content-type'].split(';')[0] in [ 'application/vnd.ogc.se_xml', 'text/xml' ]: se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = six.text_type( se_tree.find( subcommon.nspath('ServiceException', OGC_NAMESPACE)).text).strip() raise ServiceException(err_message) return request
def getmap(self, layers=None, styles=None, srs=None, bbox=None, format=None, size=None, time=None, transparent=False, bgcolor='#FFFFFF', exceptions='application/vnd.ogc.se_xml', method='Get', timeout=None, **kwargs ): """Request and return an image from the WMS as a file-like object. Parameters ---------- layers : list List of content layer names. styles : list Optional list of named styles, must be the same length as the layers list. srs : string A spatial reference system identifier. bbox : tuple (left, bottom, right, top) in srs units. format : string Output image format such as 'image/jpeg'. size : tuple (width, height) in pixels. transparent : bool Optional. Transparent background if True. bgcolor : string Optional. Image background color. method : string Optional. HTTP DCP method name: Get or Post. **kwargs : extra arguments anything else e.g. vendor specific parameters Example ------- wms = WebMapService('http://giswebservices.massgis.state.ma.us/geoserver/wms', version='1.1.1') img = wms.getmap(layers=['massgis:GISDATA.SHORELINES_ARC'],\ styles=[''],\ srs='EPSG:4326',\ bbox=(-70.8, 42, -70, 42.8),\ size=(300, 300),\ format='image/jpeg',\ transparent=True) out = open('example.jpg', 'wb') bytes_written = out.write(img.read()) out.close() """ try: base_url = next((m.get('url') for m in self.getOperationByName('GetMap').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = {'version': self.version, 'request': 'GetMap'} request = self.__build_getmap_request( layers=layers, styles=styles, srs=srs, bbox=bbox, format=format, size=size, time=time, transparent=transparent, bgcolor=bgcolor, exceptions=exceptions, **kwargs) data = urlencode(request) self.request = bind_url(base_url) + data u = openURL(base_url, data, method, timeout=timeout or self.timeout, auth=self.auth) # check for service exceptions, and return if u.info().get('Content-Type', '').split(';')[0] in ['application/vnd.ogc.se_xml']: se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = six.text_type(se_tree.find('ServiceException').text).strip() raise ServiceException(err_message) return u
def getfeature( self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname="*", maxfeatures=None, srsname=None, outputFormat=None, method="{http://www.opengis.net/wfs}Get", startindex=None, ): """Request and return feature data as a file-like object. Parameters ---------- typename : list List of typenames (string) filter : string XML-encoded OGC filter expression. bbox : tuple (left, bottom, right, top) in the feature type's coordinates. featureid : list List of unique feature ids (string) featureversion : string Default is most recent feature version. propertyname : list List of feature property names. '*' matches all. maxfeatures : int Maximum number of features to be returned. method : string Qualified name of the HTTP DCP method to use. srsname: string EPSG code to request the data in outputFormat: string (optional) Requested response format of the request. startindex: int (optional) Start position to return feature set (paging in combination with maxfeatures) There are 3 different modes of use 1) typename and bbox (simple spatial query) 2) typename and filter (more expressive) 3) featureid (direct access to known features) """ try: base_url = next( (m.get("url") for m in self.getOperationByName("GetFeature").methods if m.get("type").lower() == method.lower())) except StopIteration: base_url = self.url request = { "service": "WFS", "version": self.version, "request": "GetFeature" } # check featureid if featureid: request["featureid"] = ",".join(featureid) elif bbox and typename: request["bbox"] = ",".join([repr(x) for x in bbox]) elif filter and typename: request["filter"] = str(filter) if srsname: request["srsname"] = str(srsname) assert len(typename) > 0 request["typename"] = ",".join(typename) if propertyname is not None: if not isinstance(propertyname, list): propertyname = [propertyname] request["propertyname"] = ",".join(propertyname) if featureversion: request["featureversion"] = str(featureversion) if maxfeatures: request["maxfeatures"] = str(maxfeatures) if startindex: request["startindex"] = str(startindex) if outputFormat is not None: request["outputFormat"] = outputFormat data = urlencode(request) log.debug("Making request: %s?%s" % (base_url, data)) u = openURL(base_url, data, method, timeout=self.timeout, auth=self.auth) # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k # is data. We'll check anything smaller. if "Content-Length" in u.info(): length = int(u.info()["Content-Length"]) have_read = False else: data = u.read() have_read = True length = len(data) if length < 32000: if not have_read: data = u.read() try: tree = etree.fromstring(data) except BaseException: # Not XML return makeStringIO(data) else: if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE: se = tree.find(nspath("ServiceException", OGC_NAMESPACE)) raise ServiceException(str(se.text).strip()) else: return makeStringIO(data) else: if have_read: return makeStringIO(data) return u
def getlegendgraphic(self, layer=None, styles=None, format=None, size=None, time=None, transparent=False, bgcolor='#FFFFFF', exceptions='application/vnd.ogc.se_xml', method='Get', timeout=None, **kwargs): # Extract legend url from layer styles request = None request = self.contents[layer].getlegendgraphicrequest() # Construct legend url if request is None: try: base_url = next((m.get('url') for m in self.getOperationByName( 'GetLegendGraphic').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = {'version': self.version, 'request': 'GetLegendGraphic'} request = self.__build_getlegendgraphic_request( layer=layer, styles=styles, format=format, size=size, time=time, transparent=transparent, bgcolor=bgcolor, exceptions=exceptions, **kwargs) data = urlencode(request) ########## #Replace + with %20 ########## data = data.replace("+", "%20") request = bind_url(base_url) + data u = openURL(request, method, username=self.username, password=self.password, timeout=timeout or self.timeout) # check for service exceptions, and return if u.info()['Content-Type'].split(';')[0] in [ 'application/vnd.ogc.se_xml' ]: se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = six.text_type( se_tree.find('ServiceException').text).strip() + request raise ServiceException(err_message) return u, request
def getmap(self, layers=None, styles=None, srs=None, bbox=None, format=None, size=None, time=None, transparent=False, bgcolor='#FFFFFF', exceptions='application/vnd.ogc.se_xml', method='Get'): """Request and return an image from the WMS as a file-like object. Parameters ---------- layers : list List of content layer names. styles : list Optional list of named styles, must be the same length as the layers list. srs : string A spatial reference system identifier. bbox : tuple (left, bottom, right, top) in srs units. format : string Output image format such as 'image/jpeg'. size : tuple (width, height) in pixels. transparent : bool Optional. Transparent background if True. bgcolor : string Optional. Image background color. method : string Optional. HTTP DCP method name: Get or Post. Example ------- >>> img = wms.getmap(layers=['global_mosaic'], ... styles=['visual'], ... srs='EPSG:4326', ... bbox=(-112,36,-106,41), ... format='image/jpeg', ... size=(300,250), ... transparent=True, ... ) >>> out = open('example.jpg', 'wb') >>> out.write(img.read()) >>> out.close() """ base_url = self.getOperationByName('GetMap').methods[method]['url'] request = {'version': self.version, 'request': 'GetMap'} # check layers and styles assert len(layers) > 0 request['layers'] = ','.join(layers) if styles: assert len(styles) == len(layers) request['styles'] = ','.join(styles) else: request['styles'] = '' # size request['width'] = str(size[0]) request['height'] = str(size[1]) request['srs'] = str(srs) request['bbox'] = ','.join([str(x) for x in bbox]) request['format'] = str(format) request['transparent'] = str(transparent).upper() request['bgcolor'] = '0x' + bgcolor[1:7] request['exceptions'] = str(exceptions) if time is not None: request['time'] = str(time) data = urlencode(request) proxies = config_loader(dataset="proxies") u = openURL(base_url, data, method, username=self.username, password=self.password, proxies=proxies) # check for service exceptions, and return if u.info()['Content-Type'] == 'application/vnd.ogc.se_xml': se_xml = u.read() se_tree = etree.fromstring(se_xml) err_message = str(se_tree.find('ServiceException').text).strip() raise ServiceException(err_message, se_xml) return u
def openURL(url_base, data=None, method='Get', cookies=None, username=None, password=None, timeout=config_loader(dataset="WMS_request_timeout"), headers=None, proxies=None): # (mss) added proxies # (mss) timeout default of 30secs set by the config_loader """ Function to open URLs. Uses requests library but with additional checks for OGC service exceptions and url formatting. Also handles cookies and simple user password authentication. """ headers = headers if headers is not None else {} rkwargs = {} rkwargs['timeout'] = timeout auth = None if username and password: auth = (username, password) rkwargs['auth'] = auth # FIXUP for WFS in particular, remove xml style namespace # @TODO does this belong here? method = method.split("}")[-1] if method.lower() == 'post': try: etree.fromstring(data) headers['Content-Type'] = 'text/xml' except (ParseError, UnicodeEncodeError) as error: # (mss) logging.debug("ParseError, UnicodeEncodeError %s", error) rkwargs['data'] = data elif method.lower() == 'get': rkwargs['params'] = data else: raise ValueError( f"Unknown method ('{method}'), expected 'get' or 'post'") if cookies is not None: rkwargs['cookies'] = cookies req = requests.request( method.upper(), url_base, headers=headers, # MSS proxies=proxies, **rkwargs) if req.status_code in [400, 401]: raise ServiceException(req.text) if req.status_code in [404, 500, 502, 503, 504]: # add more if needed req.raise_for_status() # check for service exceptions without the http header set if 'Content-Type' in req.headers and req.headers['Content-Type'] in [ 'text/xml', 'application/xml', 'application/vnd.ogc.se_xml', 'application/vnd.ogc.wms_xml' ]: # just in case 400 headers were not set, going to have to read the xml to see if it's an exception report. se_tree = etree.fromstring(req.content) # to handle the variety of namespaces and terms across services # and versions, especially for "legacy" responses like WMS 1.3.0 possible_errors = [ '{http://www.opengis.net/ows}Exception', '{http://www.opengis.net/ows/1.1}Exception', '{http://www.opengis.net/ogc}ServiceException', 'ServiceException' ] for possible_error in possible_errors: serviceException = se_tree.find(possible_error) if serviceException is not None: # and we need to deal with some message nesting raise ServiceException('\n'.join([ str(t).strip() for t in serviceException.itertext() if str(t).strip() ])) return ResponseWrapper(req)
def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname=['*'], maxfeatures=None, srsname=None, outputFormat=None, method='{http://www.opengis.net/wfs}Get', timeout=None): """Request and return feature data as a file-like object. Parameters ---------- typename : list List of typenames (string) filter : string XML-encoded OGC filter expression. bbox : tuple (left, bottom, right, top) in the feature type's coordinates. featureid : list List of unique feature ids (string) featureversion : string Default is most recent feature version. propertyname : list List of feature property names. '*' matches all. maxfeatures : int Maximum number of features to be returned. method : string Qualified name of the HTTP DCP method to use. srsname: string EPSG code to request the data in outputFormat: string (optional) Requested response format of the request. timeout : number A timeout value (in seconds) for the request. There are 3 different modes of use 1) typename and bbox (simple spatial query) 2) typename and filter (more expressive) 3) featureid (direct access to known features) """ if timeout: to = timeout else: to = self.timeout try: base_url = next( (m.get('url') for m in self.getOperationByName('GetFeature').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = { 'service': 'WFS', 'version': self.version, 'request': 'GetFeature' } # check featureid if featureid: request['featureid'] = ','.join(featureid) elif bbox and typename: request['bbox'] = ','.join([repr(x) for x in bbox]) elif filter and typename: request['filter'] = str(filter) if srsname: request['srsname'] = str(srsname) assert len(typename) > 0 request['typename'] = ','.join(typename) if propertyname: request['propertyname'] = ','.join(propertyname) if featureversion: request['featureversion'] = str(featureversion) if maxfeatures: request['maxfeatures'] = str(maxfeatures) if outputFormat is not None: request["outputFormat"] = outputFormat data = urlencode(request) log.debug("Making request: %s?%s" % (base_url, data)) u = openURL(base_url, data, method, timeout=to) # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k # is data. We'll check anything smaller. try: length = int(u.info()['Content-Length']) have_read = False except (KeyError, AttributeError): data = u.read() have_read = True length = len(data) if length < 32000: if not have_read: data = u.read() try: tree = etree.fromstring(data) except BaseException: # Not XML return StringIO(data) else: if tree.tag == "{%s}ServiceExceptionReport" % OGC_NAMESPACE: se = tree.find(nspath('ServiceException', OGC_NAMESPACE)) raise ServiceException(str(se.text).strip()) else: return StringIO(data) else: if have_read: return StringIO(data) return u