From cc5b626a5440961edc681aac0d1a17dff72cb0bb Mon Sep 17 00:00:00 2001 From: Alex Grintsvayg Date: Wed, 2 Aug 2017 15:50:17 -0400 Subject: [PATCH] removed old /view and /upload endpoints, moved api to root path --- CHANGELOG.md | 4 +- lbrynet/daemon/Daemon.py | 2 +- lbrynet/daemon/DaemonControl.py | 14 ++-- lbrynet/daemon/DaemonServer.py | 32 ++++---- lbrynet/daemon/Resources.py | 137 -------------------------------- 5 files changed, 28 insertions(+), 161 deletions(-) delete mode 100644 lbrynet/daemon/Resources.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 25705ade7..0410ed0ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ at anytime. * ### Deprecated - * + * The API will no longer be served at the /lbryapi path. It will now be at the root. * ### Changed @@ -45,6 +45,8 @@ at anytime. ### Removed * Removed TempBlobManager + * Removed old /view and /upload API paths + * ## [0.14.2] - 2017-07-24 diff --git a/lbrynet/daemon/Daemon.py b/lbrynet/daemon/Daemon.py index adeb4ddf6..882360785 100644 --- a/lbrynet/daemon/Daemon.py +++ b/lbrynet/daemon/Daemon.py @@ -169,7 +169,7 @@ class Daemon(AuthJSONRPCServer): 'daemon_stop', 'status', 'version', ] - def __init__(self, root, analytics_manager): + def __init__(self, analytics_manager): AuthJSONRPCServer.__init__(self, conf.settings['use_auth_http']) self.db_dir = conf.settings['data_dir'] self.download_directory = conf.settings['download_directory'] diff --git a/lbrynet/daemon/DaemonControl.py b/lbrynet/daemon/DaemonControl.py index cb2e90217..d16492ed6 100644 --- a/lbrynet/daemon/DaemonControl.py +++ b/lbrynet/daemon/DaemonControl.py @@ -9,7 +9,6 @@ from jsonrpc.proxy import JSONRPCProxy from lbrynet import analytics from lbrynet import conf from lbrynet.core import utils, system_info -from lbrynet.daemon.auth.client import LBRYAPIClient from lbrynet.daemon.DaemonServer import DaemonServer log = logging.getLogger(__name__) @@ -89,16 +88,15 @@ def start(): def update_settings_from_args(args): - cli_settings = {} - cli_settings['use_auth_http'] = args.useauth - cli_settings['wallet'] = args.wallet - conf.settings.update(cli_settings, data_types=(conf.TYPE_CLI,)) + conf.settings.update({ + 'use_auth_http': args.useauth, + 'wallet': args.wallet, + }, data_types=(conf.TYPE_CLI,)) @defer.inlineCallbacks -def start_server_and_listen(use_auth, analytics_manager, max_tries=5): - """The primary entry point for launching the daemon. - +def start_server_and_listen(use_auth, analytics_manager): + """ Args: use_auth: set to true to enable http authentication analytics_manager: to send analytics diff --git a/lbrynet/daemon/DaemonServer.py b/lbrynet/daemon/DaemonServer.py index 59e62eb95..98c340d71 100644 --- a/lbrynet/daemon/DaemonServer.py +++ b/lbrynet/daemon/DaemonServer.py @@ -1,37 +1,41 @@ import logging import os -from twisted.web import server, guard +from twisted.web import server, guard, resource from twisted.internet import defer, reactor, error from twisted.cred import portal from lbrynet import conf from lbrynet.daemon.Daemon import Daemon -from lbrynet.daemon.Resources import LBRYindex, HostedEncryptedFile, EncryptedFileUpload from lbrynet.daemon.auth.auth import PasswordChecker, HttpPasswordRealm from lbrynet.daemon.auth.util import initialize_api_key_file from lbrynet.daemon.DaemonRequest import DaemonRequest - log = logging.getLogger(__name__) +class IndexResource(resource.Resource): + def getChild(self, name, request): + request.setHeader('cache-control', 'no-cache, no-store, must-revalidate') + request.setHeader('expires', '0') + return self if name == '' else resource.Resource.getChild(self, name, request) + + class DaemonServer(object): def __init__(self, analytics_manager=None): - self._api = None + self._daemon = None self.root = None self.server_port = None self.analytics_manager = analytics_manager def _setup_server(self, use_auth): - ui_path = os.path.join(conf.settings.ensure_data_dir(), "lbry-ui", "active") - self.root = LBRYindex(ui_path) - self._api = Daemon(self.root, self.analytics_manager) - self.root.putChild("view", HostedEncryptedFile(self._api)) - self.root.putChild("upload", EncryptedFileUpload(self._api)) - self.root.putChild(conf.settings['API_ADDRESS'], self._api) + self.root = IndexResource() + self._daemon = Daemon(self.analytics_manager) + self.root.putChild("", self._daemon) + # TODO: DEPRECATED, remove this and just serve the API at the root + self.root.putChild(conf.settings['API_ADDRESS'], self._daemon) - lbrynet_server = server.Site(get_site_base(use_auth, self.root)) + lbrynet_server = get_site_base(use_auth, self.root) lbrynet_server.requestFactory = DaemonRequest try: @@ -46,7 +50,7 @@ class DaemonServer(object): @defer.inlineCallbacks def start(self, use_auth): yield self._setup_server(use_auth) - yield self._api.setup() + yield self._daemon.setup() @defer.inlineCallbacks def stop(self): @@ -59,10 +63,10 @@ class DaemonServer(object): def get_site_base(use_auth, root): if use_auth: log.info("Using authenticated API") - return create_auth_session(root) + root = create_auth_session(root) else: log.info("Using non-authenticated API") - return server.Site(root) + return server.Site(root) def create_auth_session(root): diff --git a/lbrynet/daemon/Resources.py b/lbrynet/daemon/Resources.py deleted file mode 100644 index c6918b057..000000000 --- a/lbrynet/daemon/Resources.py +++ /dev/null @@ -1,137 +0,0 @@ -import logging -import os -import shutil -import json -import tempfile - - -from twisted.web import server, static, resource -from twisted.internet import defer, error - -from lbrynet import conf -from lbrynet.daemon.FileStreamer import EncryptedFileStreamer - -log = logging.getLogger(__name__) - - -class NoCacheStaticFile(static.File): - def _set_no_cache(self, request): - request.setHeader('cache-control', 'no-cache, no-store, must-revalidate') - request.setHeader('expires', '0') - - def render_GET(self, request): - self._set_no_cache(request) - return static.File.render_GET(self, request) - - -class LBRYindex(resource.Resource): - def __init__(self, ui_dir): - resource.Resource.__init__(self) - self.ui_dir = ui_dir - - isLeaf = False - - def _delayed_render(self, request, results): - request.write(str(results)) - request.finish() - - def getChild(self, name, request): - request.setHeader('cache-control', 'no-cache, no-store, must-revalidate') - request.setHeader('expires', '0') - - if name == '': - return self - return resource.Resource.getChild(self, name, request) - - def render_GET(self, request): - return NoCacheStaticFile(os.path.join(self.ui_dir, "index.html")).render_GET(request) - - -class HostedEncryptedFile(resource.Resource): - def __init__(self, api): - self._api = api - resource.Resource.__init__(self) - - def _make_stream_producer(self, request, stream): - path = os.path.join(self._api.download_directory, stream.file_name) - - producer = EncryptedFileStreamer(request, path, stream, self._api.lbry_file_manager) - request.registerProducer(producer, streaming=True) - - d = request.notifyFinish() - d.addErrback(self._responseFailed, d) - return d - - def is_valid_request_name(self, request): - return ( - request.args['name'][0] != 'lbry' and - request.args['name'][0] not in self._api.waiting_on.keys()) - - def render_GET(self, request): - request.setHeader("Content-Security-Policy", "sandbox") - if 'name' in request.args.keys(): - if self.is_valid_request_name(request): - name = request.args['name'][0] - d = self._api.jsonrpc_get(name=name) - d.addCallback(lambda response: response['stream_hash']) - d.addCallback(lambda sd_hash: self._api._get_lbry_file_by_sd_hash(sd_hash)) - d.addCallback(lambda lbry_file: self._make_stream_producer(request, lbry_file)) - elif request.args['name'][0] in self._api.waiting_on.keys(): - request.redirect( - conf.settings.get_ui_address() + "/?watch=" + request.args['name'][0] - ) - request.finish() - else: - request.redirect(conf.settings.get_ui_address()) - request.finish() - return server.NOT_DONE_YET - - def _responseFailed(self, err, call): - call.addErrback(lambda err: err.trap(error.ConnectionDone)) - call.addErrback(lambda err: err.trap(defer.CancelledError)) - call.addErrback(lambda err: log.info("Error: " + str(err))) - call.cancel() - - -class EncryptedFileUpload(resource.Resource): - """ - Accepts a file sent via the file upload widget in the web UI, saves - it into a temporary dir, and responds with a JSON string containing - the path of the newly created file. - """ - def __init__(self, api): - self._api = api - - def render_POST(self, request): - origfilename = request.args['file_filename'][0] - # Temp file created by request - uploaded_file = request.args['file'][0] - newpath = move_to_temp_dir_and_restore_filename(uploaded_file, origfilename) - self._api.uploaded_temp_files.append(newpath) - return json.dumps(newpath) - - -def move_to_temp_dir_and_restore_filename(uploaded_file, origfilename): - newdirpath = tempfile.mkdtemp() - newpath = os.path.join(newdirpath, origfilename) - if os.name == "nt": - # TODO: comment on why shutil.move doesn't work? - move_win(uploaded_file.name, newpath) - else: - shutil.move(uploaded_file.name, newpath) - return newpath - - -def move_win(from_path, to_path): - shutil.copy(from_path, to_path) - # TODO Still need to remove the file - # TODO deal with pylint error in cleaner fashion than this - try: - from exceptions import WindowsError as win_except - except ImportError as e: - log.error("This shouldn't happen") - win_except = Exception - try: - os.remove(from_path) - except win_except as e: - pass