Skip to content

Commit 44a4780

Browse files
committed
0.2.0 - add the cross-origin support.
Add the cross-origin support when serving the data to clients (e.g. the browser).
1 parent c052a5e commit 44a4780

File tree

2 files changed

+46
-7
lines changed

2 files changed

+46
-7
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
1. Add the Dash component project based on TypeScript. The project contains a `PlainDownloader` component.
1212
2. Add the default downloader component `Downloader`. It is implemented by using `StreamSaver.js`.
13+
3. Add the cross-origin support when serving the data to clients (e.g. the browser).
1314

1415
#### :floppy_disk: Change
1516

dash_file_cache/services/data.py

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def __init__(
6262
cache: CacheAbstract[CachedFileInfo, CachedData],
6363
service_name: str = "/cached-data",
6464
chunk_size: int = 1,
65+
allowed_cross_origin: Optional[str] = None,
6566
) -> None:
6667
"""Initialization.
6768
@@ -75,6 +76,11 @@ def __init__(
7576
7677
chunk_size: `int`
7778
The chunk size when streaming the cached file to users. The unit is `MB`.
79+
80+
allowed_cross_origin: `str | None`
81+
The allowed cross origin when serving the data. The usage should be the
82+
same as `"Access-Control-Allow-Origin"`. If this value is empty or `None`,
83+
the cross-origin will not be configured.
7884
"""
7985
if chunk_size < 1:
8086
raise ValueError('services: The argument "chunk_size" needs to be >=1.')
@@ -85,6 +91,11 @@ def __init__(
8591
self.__cache = cache
8692
self.__addr: str = service_name.strip()
8793
self.__chunk_size: int = chunk_size * 1024 * 1024
94+
self.__allowed_cross_origin: str = (
95+
allowed_cross_origin.strip()
96+
if isinstance(allowed_cross_origin, str)
97+
else ""
98+
)
8899

89100
@property
90101
def cache(self) -> CacheAbstract[CachedFileInfo, CachedData]:
@@ -101,6 +112,12 @@ def chunk_size(self, val: int) -> None:
101112
"""The chunk size when streaming the cached file to users. The unit is `MB`."""
102113
self.__chunk_size = int(val) * 1024 * 1024
103114

115+
@property
116+
def allowed_cross_origin(self) -> str:
117+
"""Property: The allowed cross origin. If this value is an empty string, the
118+
cross-origin data delivery will not be used."""
119+
return self.__allowed_cross_origin
120+
104121
def register(
105122
self,
106123
fobj: Union[str, os.PathLike, io.StringIO, io.BytesIO],
@@ -237,6 +254,32 @@ def at_closed(_ctx_fobj: IO[Any]) -> None:
237254

238255
return at_closed
239256

257+
def _stream_add_headers(
258+
self,
259+
resp: flask.Response,
260+
info: CachedFileInfo,
261+
uid: str,
262+
download: bool = False,
263+
) -> flask.Response:
264+
"""Private method of `stream()`
265+
266+
Add customized headers to the data service response."""
267+
resp.headers["Content-Length"] = str(info["data_size"])
268+
if self.__allowed_cross_origin:
269+
resp.headers["Access-Control-Allow-Origin"] = self.__allowed_cross_origin
270+
resp.headers["Access-Control-Allow-Credentials"] = "true"
271+
if download:
272+
file_name = info["file_name"]
273+
file_name = file_name if isinstance(file_name, str) and file_name else uid
274+
if self.__allowed_cross_origin:
275+
resp.headers["Access-Control-Expose-Headers"] = (
276+
"Content-Type, Content-Length, Content-Disposition"
277+
)
278+
resp.headers["Content-Disposition"] = "attachment; filename={0}".format(
279+
file_name
280+
)
281+
return resp
282+
240283
def stream(self, uid: str, download: bool = False) -> flask.Response:
241284
"""Wrap a cached data item with streaming data provider.
242285
@@ -294,13 +337,8 @@ def provider(_deferred: Callable[[], IO[AnyStr]]) -> Iterator[AnyStr]:
294337
),
295338
mimetype=info["mime_type"],
296339
)
297-
resp.headers["Content-Length"] = str(info["data_size"])
298-
if download:
299-
file_name = info["file_name"]
300-
file_name = file_name if isinstance(file_name, str) and file_name else uid
301-
resp.headers["Content-Disposition"] = "attachment; filename={0}".format(
302-
file_name
303-
)
340+
self._stream_add_headers(resp, info=info, uid=uid, download=download)
341+
print(resp.headers)
304342

305343
return resp
306344

0 commit comments

Comments
 (0)