diff options
author | David Lord <davidism@gmail.com> | 2020-07-13 22:35:10 -0700 |
---|---|---|
committer | David Lord <davidism@gmail.com> | 2020-07-13 22:35:10 -0700 |
commit | ffe81a50451736ecbd1b7c0247147f76e58f2c60 (patch) | |
tree | f477d36b03705fa6b3dbde83201d933bd3724220 /src/werkzeug/utils.py | |
parent | f32a8dfe66dbeacd31c8b10d12c77efc1e0dd1d8 (diff) | |
download | werkzeug-ffe81a50451736ecbd1b7c0247147f76e58f2c60.tar.gz |
add send_from_directory
Diffstat (limited to 'src/werkzeug/utils.py')
-rw-r--r-- | src/werkzeug/utils.py | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/src/werkzeug/utils.py b/src/werkzeug/utils.py index 47742624..51b0439e 100644 --- a/src/werkzeug/utils.py +++ b/src/werkzeug/utils.py @@ -16,7 +16,9 @@ from ._internal import _DictAccessorProperty from ._internal import _missing from ._internal import _parse_signature from .datastructures import Headers +from .exceptions import NotFound from .exceptions import RequestedRangeNotSatisfiable +from .security import safe_join from .urls import url_quote from .wsgi import wrap_file @@ -728,6 +730,41 @@ def send_file( return rv +def send_from_directory(directory, path, environ, **kwargs): + """Send a file from within a directory using :func:`send_file`. + + This is a secure way to serve files from a folder, such as static + files or uploads. Uses :func:`~werkzeug.security.safe_join` to + ensure the path coming from the client is not maliciously crafted to + point outside the specified directory. + + If the final path does not point to an existing regular file, + returns a 404 :exc:`~werkzeug.exceptions.NotFound` error. + + :param directory: The directory that ``path`` must be located under. + :param path: The path to the file to send, relative to + ``directory``. + :param environ: The WSGI environ for the current request. + :param kwargs: Arguments to pass to :func:`send_file`. + + .. versionadded:: 2.0.0 + Adapted from Flask's implementation. + """ + path = safe_join(os.fspath(directory), os.fspath(path)) + + if path is None: + raise NotFound() + + try: + if not os.path.isfile(path): + raise NotFound() + except ValueError: + # path contains null byte on Python < 3.8 + raise NotFound() + + return send_file(path, environ, **kwargs) + + def import_string(import_name, silent=False): """Imports an object based on a string. This is useful if you want to use import paths as endpoints or something similar. An import path can |