mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-09-20 14:27:42 +00:00
Add "fields" query parameter to spots and alerts API calls. Closes #140
This commit is contained in:
@@ -58,8 +58,12 @@ class APIAlertsHandler(tornado.web.RequestHandler):
|
||||
# Fetch all alerts matching the query, then optionally enrich with online data
|
||||
credentials = extract_credentials(self.request.headers)
|
||||
data = get_alert_list_with_filters(self._alerts, query_params)
|
||||
fields = [f.strip() for f in query_params["fields"].split(",")] if "fields" in query_params else []
|
||||
if credentials:
|
||||
data = self._enrich(data, credentials)
|
||||
# Filter for only the required fields, if necessary
|
||||
if fields:
|
||||
data = filter_fields(data, fields)
|
||||
self.write(safe_json_dumps(data))
|
||||
self.set_status(200)
|
||||
except ValueError as e:
|
||||
@@ -81,6 +85,7 @@ class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
|
||||
self._web_server_metrics = None
|
||||
self._query_params = None
|
||||
self._credentials = None
|
||||
self._fields = None
|
||||
super().__init__(application, request, **kwargs)
|
||||
|
||||
def initialize(self, sse_alert_broadcaster, web_server_metrics):
|
||||
@@ -104,6 +109,9 @@ class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
|
||||
# reduce that to just the first entry, and convert bytes to string
|
||||
self._query_params = {k: v[0].decode("utf-8") for k, v in self.request.arguments.items()}
|
||||
self._credentials = extract_credentials(self.request.headers)
|
||||
self._fields = (
|
||||
[f.strip() for f in self._query_params["fields"].split(",")] if "fields" in self._query_params else []
|
||||
)
|
||||
|
||||
# Flush headers immediately so nginx doesn't time out waiting for a response
|
||||
self.write_message("keepalive", "")
|
||||
@@ -126,10 +134,15 @@ class APIAlertsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
|
||||
"""Callback when a new alert arrives"""
|
||||
|
||||
try:
|
||||
# If the new alert matches our param filters, send it to the client. If not, ignore it.
|
||||
if alert_allowed_by_query(alert, self._query_params):
|
||||
# Add lookup data if we have credentials
|
||||
if self._credentials:
|
||||
alert = copy.deepcopy(alert)
|
||||
alert.infer_missing(self._credentials)
|
||||
# Filter fields returned if necessary
|
||||
if self._fields:
|
||||
alert = filter_fields([alert], self._fields)[0]
|
||||
self.write_message(msg=safe_json_dumps(alert))
|
||||
except Exception:
|
||||
logger.exception("Exception in SSE callback, connection will be closed")
|
||||
@@ -216,3 +229,9 @@ def alert_allowed_by_query(alert, query):
|
||||
):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def filter_fields(alerts, fields):
|
||||
"""Given a list of alert objects, return copies containing only the named fields."""
|
||||
|
||||
return [{k: v for k, v in alert.__dict__.items() if k in fields} for alert in alerts]
|
||||
|
||||
@@ -56,9 +56,13 @@ class APISpotsHandler(tornado.web.RequestHandler):
|
||||
|
||||
# Fetch all spots matching the query, then optionally enrich with online data
|
||||
credentials = extract_credentials(self.request.headers)
|
||||
fields = [f.strip() for f in query_params["fields"].split(",")] if "fields" in query_params else []
|
||||
data = get_spot_list_with_filters(self._spots, query_params)
|
||||
if credentials:
|
||||
data = self._enrich(data, credentials)
|
||||
# Filter for only the required fields, if necessary
|
||||
if fields:
|
||||
data = filter_fields(data, fields)
|
||||
self.write(safe_json_dumps(data))
|
||||
self.set_status(200)
|
||||
except ValueError as e:
|
||||
@@ -80,6 +84,7 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
|
||||
self._web_server_metrics = None
|
||||
self._query_params = None
|
||||
self._credentials = None
|
||||
self._fields = None
|
||||
super().__init__(application, request, **kwargs)
|
||||
|
||||
def initialize(self, sse_spot_broadcaster, web_server_metrics):
|
||||
@@ -105,6 +110,9 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
|
||||
# reduce that to just the first entry, and convert bytes to string
|
||||
self._query_params = {k: v[0].decode("utf-8") for k, v in self.request.arguments.items()}
|
||||
self._credentials = extract_credentials(self.request.headers)
|
||||
self._fields = (
|
||||
[f.strip() for f in self._query_params["fields"].split(",")] if "fields" in self._query_params else []
|
||||
)
|
||||
|
||||
# Flush headers immediately so nginx doesn't time out waiting for a response
|
||||
self.write_message("keepalive", "")
|
||||
@@ -129,9 +137,13 @@ class APISpotsStreamHandler(tornado_eventsource.handler.EventSourceHandler):
|
||||
try:
|
||||
# If the new spot matches our param filters, send it to the client. If not, ignore it.
|
||||
if spot_allowed_by_query(spot, self._query_params):
|
||||
# Add lookup data if we have credentials
|
||||
if self._credentials:
|
||||
spot = copy.deepcopy(spot)
|
||||
spot.infer_missing(self._credentials)
|
||||
# Filter fields returned if necessary
|
||||
if self._fields:
|
||||
spot = filter_fields([spot], self._fields)[0]
|
||||
self.write_message(msg=safe_json_dumps(spot))
|
||||
except Exception:
|
||||
logger.exception("Exception in SSE callback, connection will be closed")
|
||||
@@ -266,3 +278,9 @@ def spot_allowed_by_query(spot, query):
|
||||
if needs_good_location and not spot.dx_location_good:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def filter_fields(spots, fields):
|
||||
"""Given a list of spot objects, return copies containing only the named fields."""
|
||||
|
||||
return [{k: v for k, v in spot.__dict__.items() if k in fields} for spot in spots]
|
||||
|
||||
Reference in New Issue
Block a user