Skip to content

Commit

Permalink
Allow CORS from localhost by default (#197) (#236)
Browse files Browse the repository at this point in the history
  • Loading branch information
dionhaefner authored Oct 10, 2021
1 parent 9bd5873 commit 30730e7
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 15 deletions.
12 changes: 5 additions & 7 deletions terracotta/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import zlib

import numpy as np
from cachetools import LFUCache, Cache
from cachetools import LFUCache

CompressionTuple = Tuple[bytes, bytes, str, Tuple[int, int]]
SizeFunction = Callable[[CompressionTuple], int]
Expand All @@ -22,16 +22,14 @@ def __init__(self, maxsize: int, compression_level: int):
super().__init__(maxsize, self._get_size)
self.compression_level = compression_level

def __getitem__(self, key: Any,
cache_getitem: Callable = Cache.__getitem__) -> np.ma.MaskedArray:
compressed_item = super().__getitem__(key, cache_getitem)
def __getitem__(self, key: Any) -> np.ma.MaskedArray:
compressed_item = super().__getitem__(key)
return self._decompress_tuple(compressed_item)

def __setitem__(self, key: Any,
value: np.ma.MaskedArray,
cache_setitem: Callable = Cache.__setitem__) -> None:
value: np.ma.MaskedArray) -> None:
val_compressed = self._compress_ma(value, self.compression_level)
super().__setitem__(key, val_compressed, cache_setitem)
super().__setitem__(key, val_compressed)

@staticmethod
def _compress_ma(arr: np.ma.MaskedArray, compression_level: int) -> CompressionTuple:
Expand Down
2 changes: 1 addition & 1 deletion terracotta/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class TerracottaSettings(NamedTuple):
ALLOWED_ORIGINS_METADATA: List[str] = ['*']

#: CORS allowed origins for tiles endpoints
ALLOWED_ORIGINS_TILES: List[str] = []
ALLOWED_ORIGINS_TILES: List[str] = [r'http[s]?://(localhost|127\.0\.0\.1):*']

#: MySQL database username (if not given in driver path)
MYSQL_USER: Optional[str] = None
Expand Down
29 changes: 22 additions & 7 deletions terracotta/server/flask_api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any
from typing import Any, cast, Callable, Type, TYPE_CHECKING
import copy

from apispec import APISpec
Expand All @@ -12,7 +12,6 @@

from terracotta import exceptions, __version__


# define blueprints, will be populated by submodules
TILE_API = Blueprint('tile_api', 'terracotta.server')
METADATA_API = Blueprint('metadata_api', 'terracotta.server')
Expand Down Expand Up @@ -40,29 +39,45 @@ def _abort(status_code: int, message: str = '') -> Any:


def _setup_error_handlers(app: Flask) -> None:
@app.errorhandler(exceptions.TileOutOfBoundsError)
def register_error_handler(exc: Type[Exception], func: Callable[[Exception], Any]) -> None:
if TYPE_CHECKING: # pragma: no cover
# Flask defines this type only during type checking
from flask.typing import ErrorHandlerCallable
func = cast(ErrorHandlerCallable, func)

app.register_error_handler(exc, func)

def handle_tile_out_of_bounds_error(exc: Exception) -> Any:
# send empty image
from terracotta import get_settings, image
settings = get_settings()
return send_file(image.empty_image(settings.DEFAULT_TILE_SIZE), mimetype='image/png')

@app.errorhandler(exceptions.DatasetNotFoundError)
register_error_handler(exceptions.TileOutOfBoundsError, handle_tile_out_of_bounds_error)

def handle_dataset_not_found_error(exc: Exception) -> Any:
# wrong path -> 404
if current_app.debug:
raise exc
return _abort(404, str(exc))

@app.errorhandler(exceptions.InvalidArgumentsError)
@app.errorhandler(exceptions.InvalidKeyError)
@app.errorhandler(marshmallow.ValidationError)
register_error_handler(exceptions.DatasetNotFoundError, handle_dataset_not_found_error)

def handle_marshmallow_validation_error(exc: Exception) -> Any:
# wrong query arguments -> 400
if current_app.debug:
raise exc
return _abort(400, str(exc))

validation_errors = (
exceptions.InvalidArgumentsError,
exceptions.InvalidKeyError,
marshmallow.ValidationError
)

for err in validation_errors:
register_error_handler(err, handle_marshmallow_validation_error)


def create_app(debug: bool = False, profile: bool = False) -> Flask:
"""Returns a Flask app"""
Expand Down

0 comments on commit 30730e7

Please sign in to comment.