@@ -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