Skip to content

Commit 7efc5d9

Browse files
committed
extend the sniffing capability to head out to the endpoint to find out what it is
some comments: - it may return an array of protocols, if multiple are supported - for backwards compatibility, you need to set first=False to allow multiple (multiple is also slow) - you need to set extended=True to activate the extended sniffing
1 parent d99cb2c commit 7efc5d9

File tree

3 files changed

+117
-6
lines changed

3 files changed

+117
-6
lines changed

Diff for: geolinks/__init__.py

+115-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@
3131
import sys
3232

3333
import click
34+
from owslib.wms import WebMapService as WMS
35+
from owslib.wfs import WebFeatureService as WFS
36+
from owslib.ogcapi.features import Features as OAPIF
37+
from owslib.ogcapi.coverages import Coverages as OAPIC
38+
from owslib.ogcapi.records import Records as OAPIR
39+
from owslib.wcs import WebCoverageService as WCS
40+
from owslib.csw import CatalogueServiceWeb as CSW
41+
from owslib.wps import WebProcessingService as WPS
42+
from owslib.sos import SensorObservationService as SOS
43+
from owslib.wmts import WebMapTileService as WMTS
3444

3545
LOGGER = logging.getLogger(__name__)
3646

@@ -51,7 +61,6 @@ def callback(ctx, param, value):
5161
help='Verbosity',
5262
callback=callback)(f)
5363

54-
5564
def inurl(needles, haystack, position='any'):
5665
"""convenience function to make string.find return bool"""
5766

@@ -78,7 +87,7 @@ def inurl(needles, haystack, position='any'):
7887
return False
7988

8089

81-
def sniff_link(url):
90+
def sniff_link(url, extended=False, first=True):
8291
"""performs basic heuristics to detect what the URL is"""
8392

8493
protocol = None
@@ -123,7 +132,106 @@ def sniff_link(url):
123132
elif inurl(['kml', 'kmz'], link, 'end'):
124133
protocol = 'OGC:KML'
125134
else:
126-
LOGGER.info('No link type detected')
135+
if (extended):
136+
protocol = []
137+
#for each servicetype, head out to see if it is valid
138+
try:
139+
wms = WMS(link)
140+
if (wms.identification.type == 'OGC:WMS'):
141+
if (first):
142+
return wms.identification.type
143+
else:
144+
protocol.append(wms.identification.type)
145+
except:
146+
pass # No need to log?
147+
try:
148+
wmts = WMTS(link)
149+
if (wmts.identification.type == 'OGC:WMTS'):
150+
if (first):
151+
return wmts.identification.type
152+
else:
153+
protocol.append(wmts.identification.type)
154+
except:
155+
pass
156+
try:
157+
wps = WPS(link, verbose=False, skip_caps=True)
158+
wps.getcapabilities()
159+
if (wps.identification.type == 'OGC:WPS'):
160+
if (first):
161+
return wps.identification.type
162+
else:
163+
protocol.append(wps.identification.type)
164+
except:
165+
pass
166+
try:
167+
wfs = WFS(link)
168+
if (wfs.identification.type == 'OGC:WFS'):
169+
if (first):
170+
return wfs.identification.type
171+
else:
172+
protocol.append(wfs.identification.type)
173+
except:
174+
pass
175+
try:
176+
csw = CSW('http://geodiscover.cgdi.ca/wes/serviceManagerCSW/csw')
177+
if (csw.identification.type == 'OGC:CSW'):
178+
if (first):
179+
return csw.identification.type
180+
else:
181+
protocol.append(csw.identification.type)
182+
except:
183+
pass
184+
try:
185+
wcs = WCS(link)
186+
if (wcs.identification.type == 'OGC:WCS'):
187+
if (first):
188+
return wcs.identification.type
189+
else:
190+
protocol.append(wcs.identification.type)
191+
except:
192+
pass
193+
try:
194+
sos = SOS(link)
195+
if (sos.identification.type == 'OGC:SOS'):
196+
if (first):
197+
return sos.identification.type
198+
else:
199+
protocol.append(sos.identification.type)
200+
except:
201+
pass
202+
try:
203+
oapir = OAPIR(link)
204+
if (oapir.conformance()):
205+
if (first):
206+
return "OGCAPI:records"
207+
else:
208+
protocol.append("OGCAPI:records")
209+
except:
210+
pass
211+
try:
212+
oapif = OAPIF(link)
213+
if (oapir.conformance()):
214+
if (first):
215+
return "OGCAPI:features"
216+
else:
217+
protocol.append("OGCAPI:features")
218+
except:
219+
pass
220+
try:
221+
oapic = OAPIC(link)
222+
if (oapir.conformance()):
223+
if (first):
224+
return "OGCAPI:coverages"
225+
else:
226+
protocol.append("OGCAPI:coverages")
227+
except:
228+
pass
229+
230+
if len(protocol) == 1:
231+
protocol = protocol[0]
232+
233+
else:
234+
LOGGER.info('No link type detected')
127235

128236
return protocol
129237

@@ -150,8 +258,10 @@ def sniff(link, verbosity):
150258

151259
link_type = sniff_link(link)
152260

153-
click.echo(f'Link type: {link_type}')
154-
261+
if isinstance(link_type, str):
262+
click.echo(f'Link type: {link_type}')
263+
else:
264+
click.echo(f'Link types: {link_type.join(",")}')
155265

156266
link.add_command(sniff)
157267
cli.add_command(link)

Diff for: tests/run_tests.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def test_link_types(self):
5959
"""simple link type tests"""
6060

6161
for test in self.test_data['test_data']:
62-
self.assertEqual(sniff_link(test['link']), test['expected'],
62+
self.assertEqual(sniff_link(test['link'],extended=True), test['expected'],
6363
'Expected %s and %s to be equal' %
6464
(test['link'], test['expected']))
6565

Diff for: tests/test_data.json

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"test_data": [
33
{"link": "http://host/wms?service=WMS", "expected": "OGC:WMS"},
4+
{"link": "https://maps.isric.org/mapserv?map=/map/bdod.map", "expected": "OGC:WMS"},
45
{"link": "http://host/ows?service=WFS", "expected": "OGC:WFS"},
56
{"link": "http://host/ows?service=WCS", "expected": "OGC:WCS"},
67
{"link": "http://host/ows?service=WPS", "expected": "OGC:WPS"},

0 commit comments

Comments
 (0)