server alive
This commit is contained in:
parent
1c17b57d8a
commit
fab0e979d5
11 changed files with 353 additions and 28 deletions
|
@ -7,6 +7,7 @@ import re
|
|||
import falcon
|
||||
import psycopg2
|
||||
import psycopg2.extras
|
||||
import psycopg2.errors
|
||||
from oedb.models.event import BaseEvent
|
||||
from oedb.utils.db import db_connect
|
||||
from oedb.utils.serialization import dumps
|
||||
|
@ -219,7 +220,7 @@ class EventResource(BaseEvent):
|
|||
event_sort=event_sort, limit=limit)
|
||||
logger.debug(f"Executing SQL: {sql}")
|
||||
cur.execute(sql)
|
||||
resp.body = dumps(self.rows_to_collection(cur.fetchall(), geom_only))
|
||||
resp.text = dumps(self.rows_to_collection(cur.fetchall(), geom_only))
|
||||
resp.status = falcon.HTTP_200
|
||||
logger.success(f"Successfully processed GET request to /event")
|
||||
else:
|
||||
|
@ -229,16 +230,24 @@ class EventResource(BaseEvent):
|
|||
|
||||
e = cur.fetchone()
|
||||
if e is not None:
|
||||
resp.body = dumps(self.row_to_feature(e))
|
||||
resp.text = dumps(self.row_to_feature(e))
|
||||
resp.status = falcon.HTTP_200
|
||||
logger.success(f"Successfully processed GET request to /event/{id}")
|
||||
else:
|
||||
resp.status = falcon.HTTP_404
|
||||
logger.warning(f"Event not found: {id}")
|
||||
except psycopg2.errors.InsufficientPrivilege as e:
|
||||
logger.error(f"Permission denied for database table: {e}")
|
||||
resp.status = falcon.HTTP_500
|
||||
resp.text = dumps({
|
||||
"error": "Database permission error",
|
||||
"message": "The server does not have permission to access the required database tables. Please contact the administrator to fix this issue.",
|
||||
"details": str(e)
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing GET request: {e}")
|
||||
resp.status = falcon.HTTP_500
|
||||
resp.body = dumps({"error": str(e)})
|
||||
resp.text = dumps({"error": str(e)})
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
@ -260,29 +269,29 @@ class EventResource(BaseEvent):
|
|||
j = json.loads(body)
|
||||
except Exception as e:
|
||||
logger.error(f"Invalid JSON or bad encoding: {e}")
|
||||
resp.body = 'invalid json or bad encoding'
|
||||
resp.text = 'invalid json or bad encoding'
|
||||
resp.status = falcon.HTTP_400
|
||||
return
|
||||
|
||||
resp.body = ''
|
||||
resp.text = ''
|
||||
if "properties" not in j:
|
||||
resp.body = resp.body + "missing 'properties' elements\n"
|
||||
resp.text = resp.text + "missing 'properties' elements\n"
|
||||
j['properties'] = dict()
|
||||
if "geometry" not in j:
|
||||
resp.body = resp.body + "missing 'geometry' elements\n"
|
||||
resp.text = resp.text + "missing 'geometry' elements\n"
|
||||
j['geometry'] = None
|
||||
if "when" not in j['properties'] and ("start" not in j['properties'] or "stop" not in j['properties']):
|
||||
resp.body = resp.body + "missing 'when' or 'start/stop' in properties\n"
|
||||
resp.text = resp.text + "missing 'when' or 'start/stop' in properties\n"
|
||||
j['properties']['when'] = None
|
||||
if "type" not in j['properties']:
|
||||
resp.body = resp.body + "missing 'type' of event in properties\n"
|
||||
resp.text = resp.text + "missing 'type' of event in properties\n"
|
||||
j['properties']['type'] = None
|
||||
if "what" not in j['properties']:
|
||||
resp.body = resp.body + "missing 'what' in properties\n"
|
||||
resp.text = resp.text + "missing 'what' in properties\n"
|
||||
j['properties']['what'] = None
|
||||
if "type" in j and j['type'] != 'Feature':
|
||||
resp.body = resp.body + 'geojson must be "type":"Feature" only\n'
|
||||
if id is None and resp.body != '':
|
||||
resp.text = resp.text + 'geojson must be "type":"Feature" only\n'
|
||||
if id is None and resp.text != '':
|
||||
resp.status = falcon.HTTP_400
|
||||
resp.set_header('Content-type', 'text/plain')
|
||||
return
|
||||
|
@ -319,7 +328,7 @@ class EventResource(BaseEvent):
|
|||
geometry = dumps(j['geometry'])
|
||||
h = self.maybe_insert_geometry(geometry, cur)
|
||||
if len(h) > 1 and h[1] is False:
|
||||
resp.body = "invalid geometry: %s\n" % h[2]
|
||||
resp.text = "invalid geometry: %s\n" % h[2]
|
||||
resp.status = falcon.HTTP_400
|
||||
resp.set_header('Content-type', 'text/plain')
|
||||
return
|
||||
|
@ -361,11 +370,11 @@ class EventResource(BaseEvent):
|
|||
AND e.events_when=tstzrange(coalesce(%s, lower(s.events_when)),coalesce(%s,upper(s.events_when)),%s) AND e.events_geo=coalesce(%s, s.events_geo);""",
|
||||
(id, j['properties']['what'], event_start, event_stop, bounds, h[0]))
|
||||
dupe = cur.fetchone()
|
||||
resp.body = """{"duplicate":"%s"}""" % (dupe[0])
|
||||
resp.text = """{"duplicate":"%s"}""" % (dupe[0])
|
||||
resp.status = '409 Conflict with event %s' % dupe[0]
|
||||
logger.warning(f"Duplicate event: {dupe[0]}")
|
||||
else:
|
||||
resp.body = """{"id":"%s"}""" % (e[0])
|
||||
resp.text = """{"id":"%s"}""" % (e[0])
|
||||
if id is None:
|
||||
resp.status = falcon.HTTP_201
|
||||
logger.success(f"Event created with ID: {e[0]}")
|
||||
|
@ -455,7 +464,7 @@ class EventResource(BaseEvent):
|
|||
except Exception as e:
|
||||
logger.error(f"Error deleting event {id}: {e}")
|
||||
resp.status = falcon.HTTP_500
|
||||
resp.body = dumps({"error": str(e)})
|
||||
resp.text = dumps({"error": str(e)})
|
||||
db.rollback()
|
||||
finally:
|
||||
cur.close()
|
||||
|
|
49
oedb/resources/root.py
Normal file
49
oedb/resources/root.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
"""
|
||||
Root resource for the OpenEventDatabase.
|
||||
"""
|
||||
|
||||
import falcon
|
||||
from oedb.utils.serialization import dumps
|
||||
from oedb.utils.logging import logger
|
||||
|
||||
class RootResource:
|
||||
"""
|
||||
Resource for the root endpoint.
|
||||
Handles the / endpoint.
|
||||
"""
|
||||
|
||||
def on_get(self, req, resp):
|
||||
"""
|
||||
Handle GET requests to the / endpoint.
|
||||
Returns a JSON response with available routes and a welcome message.
|
||||
|
||||
Args:
|
||||
req: The request object.
|
||||
resp: The response object.
|
||||
"""
|
||||
logger.info("Processing GET request to /")
|
||||
|
||||
try:
|
||||
# Create a response with available routes and a welcome message
|
||||
response = {
|
||||
"message": "Welcome to the OpenEventDatabase API!",
|
||||
"available_routes": {
|
||||
"/": "This endpoint - provides information about available routes",
|
||||
"/event": "Get events matching specified criteria",
|
||||
"/event/{id}": "Get a specific event by ID",
|
||||
"/event/search": "Search for events using a GeoJSON geometry",
|
||||
"/stats": "Get statistics about the database"
|
||||
}
|
||||
}
|
||||
|
||||
# Set the response body and status
|
||||
resp.text = dumps(response)
|
||||
resp.status = falcon.HTTP_200
|
||||
logger.success("Successfully processed GET request to /")
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing GET request to /: {e}")
|
||||
resp.status = falcon.HTTP_500
|
||||
resp.text = dumps({"error": str(e)})
|
||||
|
||||
# Create a global instance of RootResource
|
||||
root = RootResource()
|
|
@ -33,7 +33,7 @@ class EventSearch(BaseEvent):
|
|||
if 'geometry' not in j:
|
||||
logger.warning("Request body missing 'geometry' field")
|
||||
resp.status = falcon.HTTP_400
|
||||
resp.body = json.dumps({"error": "Request body must contain a 'geometry' field"})
|
||||
resp.text = json.dumps({"error": "Request body must contain a 'geometry' field"})
|
||||
return
|
||||
|
||||
# Pass the query with the geometry to event.on_get
|
||||
|
@ -44,8 +44,8 @@ class EventSearch(BaseEvent):
|
|||
except json.JSONDecodeError as e:
|
||||
logger.error(f"Error decoding JSON: {e}")
|
||||
resp.status = falcon.HTTP_400
|
||||
resp.body = json.dumps({"error": "Invalid JSON in request body"})
|
||||
resp.text = json.dumps({"error": "Invalid JSON in request body"})
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing POST request to /event/search: {e}")
|
||||
resp.status = falcon.HTTP_500
|
||||
resp.body = json.dumps({"error": str(e)})
|
||||
resp.text = json.dumps({"error": str(e)})
|
|
@ -45,13 +45,13 @@ class StatsResource:
|
|||
cur.execute("SELECT row_to_json(stat) from (SELECT events_what as what, left(max(upper(events_when))::text,19) as last, count(*) as count, array_agg(distinct(regexp_replace(regexp_replace(events_tags ->> 'source','^(http://|https://)',''),'/.*',''))) as source from (select * from events order by lastupdate desc limit 10000) as last group by 1 order by 2 desc) as stat;")
|
||||
recent = cur.fetchall()
|
||||
|
||||
resp.body = dumps(dict(events_count=count, last_updated=last, uptime=uptime, db_uptime=pg_uptime, recent=recent))
|
||||
resp.text = dumps(dict(events_count=count, last_updated=last, uptime=uptime, db_uptime=pg_uptime, recent=recent))
|
||||
resp.status = falcon.HTTP_200
|
||||
logger.success("Successfully processed GET request to /stats")
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing GET request to /stats: {e}")
|
||||
resp.status = falcon.HTTP_500
|
||||
resp.body = dumps({"error": str(e)})
|
||||
resp.text = dumps({"error": str(e)})
|
||||
finally:
|
||||
cur.close()
|
||||
db.close()
|
Loading…
Add table
Add a link
Reference in a new issue