Add ability to browse multiple locations defined in ResourceLocation
This commit is contained in:
parent
b8b8fe0fb4
commit
2ad8be7aa2
65
playlistcast/api/browse.py
Normal file
65
playlistcast/api/browse.py
Normal file
@ -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)
|
9
playlistcast/api/error.py
Normal file
9
playlistcast/api/error.py
Normal file
@ -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)
|
||||
|
10
server.py
10
server.py
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user