diff --git a/tests/loaders/test_file_loader_http_fallback.py b/tests/loaders/test_file_loader_http_fallback.py index b7ee52876..820f9a0bc 100644 --- a/tests/loaders/test_file_loader_http_fallback.py +++ b/tests/loaders/test_file_loader_http_fallback.py @@ -31,6 +31,7 @@ async def dummy_file_load( successful=True, buffer="file", ) + return result @@ -41,6 +42,7 @@ async def dummy_http_load( successful=True, buffer="http", ) + return result @@ -70,3 +72,18 @@ async def test_should_load_http(self): expect(result).to_be_instance_of(LoaderResult) expect(result.buffer).to_equal("http") + + @patch.object(thumbor.loaders.http_loader, "load", dummy_http_load) + @gen_test + async def test_should_fail_with_disallowed_origin(self): + url = "http:/www.google.com/example_image.png" + config = Config(ALLOWED_SOURCES=[".+.domain1.com"]) + ctx = Context(None, config, None) + + result = await loader.load(ctx, url) + + expect(result).to_be_instance_of(LoaderResult) + expect(result.successful).to_be_false() + expect(result.error).to_equal(LoaderResult.ERROR_BAD_REQUEST) + expect(result.extras["reason"]).to_equal("Unallowed domain") + expect(result.extras["source"]).to_equal(url) diff --git a/thumbor/loaders/__init__.py b/thumbor/loaders/__init__.py index d2eed95cb..b4f1fcca3 100644 --- a/thumbor/loaders/__init__.py +++ b/thumbor/loaders/__init__.py @@ -8,14 +8,24 @@ # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 globo.com thumbor@googlegroups.com +from typing import Dict + class LoaderResult: ERROR_NOT_FOUND = "not_found" ERROR_UPSTREAM = "upstream" ERROR_TIMEOUT = "timeout" - - def __init__(self, buffer=None, successful=True, error=None, metadata=None): + ERROR_BAD_REQUEST = "bad_request" + + def __init__( + self, + buffer: bytes = None, + successful: bool = True, + error: str = None, + metadata: Dict[str, any] = None, + extras: Dict[str, any] = None, + ): """ :param buffer: The media buffer @@ -27,12 +37,19 @@ def __init__(self, buffer=None, successful=True, error=None, metadata=None): :param metadata: Dictionary of metadata about the buffer :type metadata: dict + + :param extras: Dictionary of extra information about the error + :type metadata: dict """ if metadata is None: metadata = {} + if extras is None: + extras = {} + self.buffer = buffer self.successful = successful self.error = error self.metadata = metadata + self.extras = extras diff --git a/thumbor/loaders/file_loader_http_fallback.py b/thumbor/loaders/file_loader_http_fallback.py index 816e133a0..f18329e63 100644 --- a/thumbor/loaders/file_loader_http_fallback.py +++ b/thumbor/loaders/file_loader_http_fallback.py @@ -8,14 +8,25 @@ # http://www.opensource.org/licenses/mit-license # Copyright (c) 2011 globo.com thumbor@googlegroups.com -from thumbor.loaders import file_loader, http_loader +from thumbor.loaders import LoaderResult, file_loader, http_loader async def load(context, path): # First attempt to load with file_loader result = await file_loader.load(context, path) + if result.successful: return result # If file_loader failed try http_loader + + if not http_loader.validate(context, path): + result = LoaderResult() + result.successful = False + result.error = LoaderResult.ERROR_BAD_REQUEST + result.extras["reason"] = "Unallowed domain" + result.extras["source"] = path + + return result + return await http_loader.load(context, path)