diff --git a/src/api/__init__.py b/src/api/__init__.py index ca0bc1d..4fd5f7b 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -1,10 +1,12 @@ from flask_restx import Api from .search import api as searchNamespace +from .get import api as getNamespace api = Api( - title='Search', + title='Memes', version=1.0, - description='Searching the collection' + description='A programatic interface to my meme collection' ) api.add_namespace(searchNamespace) +api.add_namespace(getNamespace) diff --git a/src/api/clientGetter.py b/src/api/clientGetter.py new file mode 100644 index 0000000..0391f63 --- /dev/null +++ b/src/api/clientGetter.py @@ -0,0 +1,12 @@ +import logging +import s3Client + +def getClientSafely(): + logging.debug("Getting a client safely...") + client = None + try: + client = s3Client.getClient() + except Exception as e: + logging.critical("Failed to retrive a client : " + str(e)) + + return client diff --git a/src/api/get.py b/src/api/get.py new file mode 100644 index 0000000..46d5dab --- /dev/null +++ b/src/api/get.py @@ -0,0 +1,28 @@ +from flask_restx import Namespace, Resource, fields +from flask_restx import reqparse +from flask import make_response +from api.clientGetter import getClientSafely +import logging + +# Exported namespace +api = Namespace('resource', description='Interact with the raw underlying resource') + +@api.route('/exact/') +@api.doc(description="Returns the raw file. This endpoint expects exact files, NOT json") +class getExactFile(Resource): + @api.doc('get') + @api.response(200, 'Sucess') + @api.response(500, 'S3 Error') + @api.response(404, 'Requested file not found') + def get(self, file_name): + client = getClientSafely() + if client is None: + return { + "message" : "Error connecting to S3" + }, 500 + if file_name in client.getCurrentMemeList(): + return make_response(client.getMeme(file_name)) + else: + return { + "message": "Requested file '" + file_name + "' not found" + }, 404 diff --git a/src/api/search.py b/src/api/search.py index 64f4b90..931d520 100644 --- a/src/api/search.py +++ b/src/api/search.py @@ -1,21 +1,11 @@ from flask_restx import Namespace, Resource, fields from flask_restx import reqparse -import s3Client +from api.clientGetter import getClientSafely import logging # Exported namespace api = Namespace('search', description='Searching for memes') -def getClientSafely(): - logging.debug("Getting a client safely...") - client = None - try: - client = s3Client.getClient() - except Exception as e: - logging.critical("Failed to retrive a client : " + str(e)) - - return client - @api.route('/exact/') @api.doc(params={ @@ -26,7 +16,6 @@ class exactSearch(Resource): @api.response(200, 'Sucess') @api.response(500, 'S3 Error') def get(self, query): - logging.debug("Getting a client safely...") client = getClientSafely() if client is None: return { diff --git a/src/s3Client.py b/src/s3Client.py index eeb1f55..2333ca0 100644 --- a/src/s3Client.py +++ b/src/s3Client.py @@ -14,6 +14,7 @@ S3_UN = "" S3_PW = "" S3_TLS = True S3_BUCKET = "" +CACHE_TTL = 10 gclient = None @@ -86,6 +87,9 @@ class Client: raise Exception("Improper object passed for client!") def getCurrentMemeList(self, force=False): + """ + Get a list of all memes in the bucket + """ now = datetime.now() if (now - self.lastCheckedAllMemes).seconds > 300 or force: logging.info("Enough time has elapsed, refreshing meme cache...") @@ -102,4 +106,19 @@ class Client: return self.allMemes + def getMeme(self, memeName: str): + """ + Return a meme with the exact given name, or raise an exception + """ + if not isinstance(memeName, str): + raise Exception("paramater memeName is of improper type, expected a str") + + memeSet = self.getCurrentMemeList() + if memeName in memeSet: + reply = self.client.get_object(bucket_name=S3_BUCKET, + object_name=memeName) + return reply.read() + else: + raise Exception("Requested meme '" + memeName + "' not found") + return None