diff --git a/main.py b/main.py index af74cce..d0d7bb5 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,12 @@ import logging from seatable_thumbnail import DBSession -from seatable_thumbnail.serializers import ThumbnailSerializer +from seatable_thumbnail.serializers import ThumbnailSerializer, PluginSerializer from seatable_thumbnail.permissions import ThumbnailPermission from seatable_thumbnail.thumbnail import Thumbnail +from seatable_thumbnail.plugin import Plugin from seatable_thumbnail.http_request import HTTPRequest -from seatable_thumbnail.http_response import gen_error_response, \ +from seatable_thumbnail.http_response import gen_error_response, gen_plugin_response, \ gen_text_response, gen_thumbnail_response, gen_cache_response logger = logging.getLogger(__name__) @@ -110,6 +111,65 @@ async def __call__(self, scope, receive, send): await send(response_body) return +# ===== plugin ===== + elif 'dtable-plugins/' == request.url[:15]: + db_session = DBSession() + + # serializer + try: + serializer = PluginSerializer(db_session, request) + plugin_info = serializer.plugin_info + except Exception as e: + logger.exception(e) + db_session.close() + response_start, response_body = gen_error_response( + 400, 'Bad request.') + await send(response_start) + await send(response_body) + return + + db_session.close() + + # cache + try: + etag = plugin_info.get('etag') + if_none_match_headers = request.headers.get('if-none-match') + if_none_match = if_none_match_headers[0] if if_none_match_headers else '' + + last_modified = plugin_info.get('last_modified') + if_modified_since_headers = request.headers.get('if-modified-since') + if_modified_since = if_modified_since_headers[0] if if_modified_since_headers else '' + + if (if_none_match and if_none_match == etag) \ + or (if_modified_since and if_modified_since == last_modified): + response_start, response_body = gen_cache_response() + await send(response_start) + await send(response_body) + return + except Exception as e: + logger.exception(e) + + # get + try: + plugin = Plugin(**plugin_info) + body = plugin.body + content_type = plugin.content_type + last_modified = plugin.last_modified + etag = plugin.etag + + response_start, response_body = gen_plugin_response( + body, content_type, etag, last_modified) + await send(response_start) + await send(response_body) + return + except Exception as e: + logger.exception(e) + response_start, response_body = gen_error_response( + 500, 'Internal server error.') + await send(response_start) + await send(response_body) + return + # ===== Not found ===== else: response_start, response_body = gen_error_response( diff --git a/seatable_thumbnail/http_response.py b/seatable_thumbnail/http_response.py index ef27546..c026015 100644 --- a/seatable_thumbnail/http_response.py +++ b/seatable_thumbnail/http_response.py @@ -51,3 +51,16 @@ def gen_thumbnail_response(thumbnail, etag, last_modified): response_start['headers'].append([b'Last-Modified', last_modified.encode('utf-8')]) return response_start, response_body + + +def gen_plugin_response(plugin, content_type, etag, last_modified): + response_start = gen_response_start(200, content_type) + response_body = gen_response_body(plugin) + + # cache + if plugin: + response_start['headers'].append([b'Cache-Control', b'max-age=86400, public']) + response_start['headers'].append([b'ETag', etag.encode('utf-8')]) + response_start['headers'].append([b'Last-Modified', last_modified.encode('utf-8')]) + + return response_start, response_body diff --git a/seatable_thumbnail/serializers.py b/seatable_thumbnail/serializers.py index 60d6b89..0e5304a 100644 --- a/seatable_thumbnail/serializers.py +++ b/seatable_thumbnail/serializers.py @@ -2,13 +2,14 @@ import uuid import json import base64 +import mimetypes from email.utils import formatdate from seaserv import seafile_api import seatable_thumbnail.settings as settings from seatable_thumbnail.constants import FILE_EXT_TYPE_MAP, \ IMAGE, PSD, VIDEO, XMIND -from seatable_thumbnail.models import Workspaces, DjangoSession +from seatable_thumbnail.models import Workspaces, DjangoSession, DTableSystemPlugins class ThumbnailSerializer(object): @@ -22,7 +23,6 @@ def check(self): self.params_check() self.session_check() self.resource_check() - self.gen_thumbnail_info() def gen_thumbnail_info(self): thumbnail_info = {} @@ -133,3 +133,60 @@ def exist_check(self, thumbnail_path): return True, last_modified else: return False, '' + + +class PluginSerializer(object): + def __init__(self, db_session, request): + self.db_session = db_session + self.request = request + self.check() + self.gen_plugin_info() + + def check(self): + self.params_check() + self.resource_check() + + def gen_plugin_info(self): + plugin_info = {} + plugin_info.update(self.params) + plugin_info.update(self.resource) + self.plugin_info = plugin_info + + def params_check(self): + path = self.request.query_dict['path'][0] + plugin_name = self.request.url.split('/')[1] + timestamp = self.request.query_dict['t'][0] if self.request.query_dict.get('t') else '' + version = self.request.query_dict['version'][0] if self.request.query_dict.get('version') else '' + content_type = mimetypes.guess_type(path) + + self.params = { + 'path': path, + 'plugin_name': plugin_name, + 'timestamp': timestamp, + 'version': version, + 'content_type': content_type, + } + + def resource_check(self): + path = self.params['path'] + plugin_name = self.params['plugin_name'] + + plugin = self.db_session.query( + DTableSystemPlugins).filter_by(name=plugin_name).first() + + file_path ='/' + plugin.name + path + repo_id = settings.PLUGINS_REPO_ID + file_id = seafile_api.get_file_id_by_path(repo_id, file_path) + if not file_id: + raise ValueError(404, 'file_id not found.') + + info = json.loads(plugin.info) + last_modified = info['last_modified'] + etag = '"' + file_id + '"' + + self.resource = { + 'file_id': file_id, + 'info': info, + 'last_modified': last_modified, + 'etag': etag, + } \ No newline at end of file