Add ability to browse multiple locations defined in ResourceLocation

This commit is contained in:
Michal Szczepanski 2020-02-27 20:50:16 +01:00
parent b8b8fe0fb4
commit 2ad8be7aa2
4 changed files with 78 additions and 10 deletions

@ -0,0 +1,65 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Serve static files using ResourceLocation defined resources"""
import os
from typing import Optional
import urllib.parse
import tornado.web
from playlistcast import db
from playlistcast.api import error
class BrowseResourceHandler(tornado.web.StaticFileHandler):
"""Serve attached resources"""
# pylint: disable=W0223
def initialize(self):
"""Override hack"""
self.root = ''
def set_etag_header(self):
"""Override hack"""
pass
@classmethod
def get_absolute_path(cls, root: str, path: str):
"""Override hack"""
return path
def validate_absolute_path(self, root: str, absolute_path: str) -> Optional[str]:
"""Override hack"""
return absolute_path
async def get(self, *args, **kwargs):
"""Get request"""
a = args[0].split('/')
model = db.session.query(db.ResourceLocation).filter(db.ResourceLocation.name == a[0]).first()
if not model:
raise error.ResourcePathError('Invalid path {}'.format(args[0]))
uri = '/resource/'
if len(a) > 0:
uri += args[0]
path = os.path.join(model.location, '/'.join(a[1:]))
else:
path = model.location
if not os.path.exists(path):
raise error.ResourcePathError('Path not exists {}'.format(path))
if os.path.isdir(path):
content = ''
back = '/'.join(uri.split('/')[:-1])
# back link if not absolute
if back != '/resource':
content = '<a href={}>..</a><br />'.format(urllib.parse.quote(back))
for name in sorted(os.listdir(path)):
content += '<a href={path}>{name}</a><br />'.format(**{
'name': name,
'path': urllib.parse.quote(uri+'/'+name),
})
msg = """<html>
<body>
%s
</body>
</html>
""" % content
self.finish(msg)
else:
await tornado.web.StaticFileHandler.get(self, path)

@ -0,0 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tornado.web
class ResourcePathError(tornado.web.HTTPError):
code = 1001
def __init__(self, message):
tornado.web.HTTPError.__init__(self, reason=message)

@ -36,11 +36,11 @@ class Query(graphene.ObjectType):
fs.value = cache.FIRST_START
return fs
def resolve_all_resource_location(self, info):
def resolve_all_resource_location(self, info: ResolveInfo) -> List[ResourceLocation]:
"""Return ResourceLocation list"""
return ResourceLocation.get_query(info).all()
def resolve_resource_location(self, info, id):
def resolve_resource_location(self, info: ResolveInfo, id: graphene.ID) -> ResourceLocation:
"""Return ResourceLocation"""
id = from_global_id(id)[1]
return ResourceLocation.get_node(info, id)

@ -8,6 +8,7 @@ import graphene
import tornado.web
import tornado.ioloop
from playlistcast.api import Subscription, Query, Mutation
from playlistcast.api import browse
# https://stackoverflow.com/a/18812776
# Add vendor directory to module search path
@ -29,13 +30,6 @@ class IndexHandler(tornado.web.RequestHandler):
with open(path, 'rb') as file:
self.finish(file.read())
class ResourceHandler(tornado.web.RequestHandler):
"""Serve attached resources"""
# pylint: disable=W0223
def get(self):
"""Get request"""
print(self.path_kwargs, self.path_args)
self.finish('')
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
@ -54,7 +48,7 @@ if __name__ == '__main__':
(r'/graphiql', GraphiQLHandler),
(r'/static/(.*)', tornado.web.StaticFileHandler, {'path': STATIC_PATH}),
(r'/', IndexHandler),
(r'/resource/(.*)', ResourceHandler),
(r'/resource/(.*)', browse.BrowseResourceHandler),
]
APP = tornado.web.Application(ENDPOINTS)
APP.listen(PORT, HOST)