2929
3030import json
3131import logging
32+ import requests
3233from pathlib import Path
3334from urllib .parse import urlparse
3435
3536from pygeoapi .provider .tile import (
3637 ProviderTileNotFoundError )
37- from pygeoapi .provider .base import ProviderConnectionError
38+ from pygeoapi .provider .base import (ProviderConnectionError ,
39+ ProviderInvalidQueryError ,
40+ ProviderGenericError )
3841from pygeoapi .provider .base_mvt import BaseMVTProvider
3942from pygeoapi .models .provider .base import (
4043 TileSetMetadata , LinkType )
@@ -69,20 +72,29 @@ def __init__(self, BaseMVTProvider):
6972 if is_url (self .data ):
7073 url = urlparse (self .data )
7174 baseurl = f'{ url .scheme } ://{ url .netloc } '
72- param_type = '?f=mvt'
75+ extension = Path ( url . path ). suffix # e.g. ".pbf"
7376 layer = f'/{ self .get_layer ()} '
7477
7578 LOGGER .debug ('Extracting layer name from URL' )
7679 LOGGER .debug (f'Layer: { layer } ' )
7780
7881 tilepath = f'{ layer } /tiles'
79- servicepath = f'{ tilepath } /{{tileMatrixSetId}}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}{ param_type } ' # noqa
82+ servicepath = f'{ tilepath } /{{tileMatrixSetId}}/{{tileMatrix}}/{{tileRow}}/{{tileCol}}{ extension } ' # noqa
8083
8184 self ._service_url = url_join (baseurl , servicepath )
8285
8386 self ._service_metadata_url = url_join (
8487 self .service_url .split ('{tileMatrix}/{tileRow}/{tileCol}' )[0 ],
8588 'metadata' )
89+
90+ metadata_path = f'{ baseurl } /{ layer } /metadata.json'
91+ head = requests .head (metadata_path )
92+ if head .status_code != 200 :
93+ msg = f'Service metadata does not exist: { metadata_path } '
94+ LOGGER .error (msg )
95+ LOGGER .warning (msg )
96+ self ._service_metadata_url = metadata_path
97+
8698 # Pre-rendered tiles served from a local path
8799 else :
88100 data_path = Path (self .data )
@@ -144,6 +156,60 @@ def get_tiles_service(self, baseurl=None, servicepath=None,
144156 self ._service_url = servicepath
145157 return self .get_tms_links ()
146158
159+ def get_tiles_from_url (self , layer = None , tileset = None ,
160+ z = None , y = None , x = None , format_ = None ):
161+ """
162+ Gets tile from a static url (e.g.: bucket, file server)
163+
164+ :param layer: mvt tile layer
165+ :param tileset: mvt tileset
166+ :param z: z index
167+ :param y: y index
168+ :param x: x index
169+ :param format_: tile format
170+
171+ :returns: an encoded mvt tile
172+ """
173+
174+ url = urlparse (self .data )
175+ base_url = f'{ url .scheme } ://{ url .netloc } '
176+
177+ extension = Path (url .path ).suffix # e.g. ".pbf"
178+
179+ try :
180+ with requests .Session () as session :
181+ session .get (base_url )
182+ resp = session .get (f'{ base_url } /{ layer } /{ z } /{ y } /{ x } { extension } ' ) # noqa
183+ resp .raise_for_status ()
184+ return resp .content
185+ except requests .exceptions .RequestException as e :
186+ LOGGER .debug (e )
187+ if resp .status_code < 500 :
188+ raise ProviderInvalidQueryError # Client is sending an invalid request # noqa
189+ raise ProviderGenericError # Server error
190+
191+ def get_tiles_from_disk (self , layer = None , tileset = None ,
192+ z = None , y = None , x = None , format_ = None ):
193+ """
194+ Gets tile from a path on disk
195+
196+ :param layer: mvt tile layer
197+ :param tileset: mvt tileset
198+ :param z: z index
199+ :param y: y index
200+ :param x: x index
201+ :param format_: tile format
202+
203+ :returns: an encoded mvt tile
204+ """
205+
206+ try :
207+ service_url_path = self .service_url .joinpath (f'{ z } /{ y } /{ x } .{ format_ } ' ) # noqa
208+ with open (service_url_path , mode = 'rb' ) as tile :
209+ return tile .read ()
210+ except FileNotFoundError as err :
211+ raise ProviderTileNotFoundError (err )
212+
147213 def get_tiles (self , layer = None , tileset = None ,
148214 z = None , y = None , x = None , format_ = None ):
149215 """
@@ -162,17 +228,14 @@ def get_tiles(self, layer=None, tileset=None,
162228 if format_ == 'mvt' :
163229 format_ = self .format_type
164230
165- if not isinstance (self .service_url , Path ):
166- msg = f'Wrong data path configuration: { self .service_url } '
231+ if isinstance (self .service_url , Path ):
232+ return self .get_tiles_from_disk (layer , tileset , z , y , x , format_ )
233+ elif is_url (self .data ):
234+ return self .get_tiles_from_url (layer , tileset , z , y , x , format_ )
235+ else :
236+ msg = 'Wrong input format for Tippecanoe MVT'
167237 LOGGER .error (msg )
168238 raise ProviderConnectionError (msg )
169- else :
170- try :
171- service_url_path = self .service_url .joinpath (f'{ z } /{ y } /{ x } .{ format_ } ' ) # noqa
172- with open (service_url_path , mode = 'rb' ) as tile :
173- return tile .read ()
174- except FileNotFoundError as err :
175- raise ProviderTileNotFoundError (err )
176239
177240 def get_html_metadata (self , dataset , server_url , layer , tileset ,
178241 title , description , keywords , ** kwargs ):
0 commit comments