Skip to content

Commit 62752ad

Browse files
committed
Expose http_cache parameter, with its docs and recipe.
1 parent 3062770 commit 62752ad

File tree

1 file changed

+56
-1
lines changed

1 file changed

+56
-1
lines changed

msal/application.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ def __init__(
170170
# This way, it holds the same positional param place for PCA,
171171
# when we would eventually want to add this feature to PCA in future.
172172
exclude_scopes=None,
173+
http_cache=None,
173174
):
174175
"""Create an instance of application.
175176
@@ -336,6 +337,60 @@ def __init__(
336337
If that is unnecessary or undesirable for your app,
337338
now you can use this parameter to supply an exclusion list of scopes,
338339
such as ``exclude_scopes = ["offline_access"]``.
340+
341+
:param dict http_cache:
342+
MSAL has long been caching tokens in the ``token_cache``.
343+
Recently, MSAL also introduced a concept of ``http_cache``,
344+
by automatically caching some finite amount of non-token http responses,
345+
so that *long-lived*
346+
``PublicClientApplication`` and ``ConfidentialClientApplication``
347+
would be more performant and responsive in some situations.
348+
349+
This ``http_cache`` parameter accepts any dict-like object.
350+
If not provided, MSAL will use an in-memory dict.
351+
352+
If your app is a command-line app (CLI),
353+
you would want to persist your http_cache across different CLI runs.
354+
The following recipe shows a way to do so::
355+
356+
# Just add the following lines at the beginning of your CLI script
357+
import sys, atexit, pickle
358+
http_cache_filename = sys.argv[0] + ".http_cache"
359+
try:
360+
with open(http_cache_filename, "rb") as f:
361+
persisted_http_cache = pickle.load(f) # Take a snapshot
362+
except (
363+
IOError, # A non-exist http cache file
364+
pickle.UnpicklingError, # A corrupted http cache file
365+
EOFError, # An empty http cache file
366+
AttributeError, ImportError, IndexError, # Other corruption
367+
):
368+
persisted_http_cache = {} # Recover by starting afresh
369+
atexit.register(lambda: pickle.dump(
370+
# When exit, flush it back to the file.
371+
# It may occasionally overwrite another process's concurrent write,
372+
# but that is fine. Subsequent runs will reach eventual consistency.
373+
persisted_http_cache, open(http_cache_file, "wb")))
374+
375+
# And then you can implement your app as you normally would
376+
app = msal.PublicClientApplication(
377+
"your_client_id",
378+
...,
379+
http_cache=persisted_http_cache, # Utilize persisted_http_cache
380+
...,
381+
#token_cache=..., # You may combine the old token_cache trick
382+
# Please refer to token_cache recipe at
383+
# https://msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
384+
)
385+
app.acquire_token_interactive(["your", "scope"], ...)
386+
387+
Content inside ``http_cache`` are cheap to obtain.
388+
There is no need to share them among different apps.
389+
390+
Content inside ``http_cache`` will contain no tokens nor
391+
Personally Identifiable Information (PII). Encryption is unnecessary.
392+
393+
New in version 1.16.0.
339394
"""
340395
self.client_id = client_id
341396
self.client_credential = client_credential
@@ -370,7 +425,7 @@ def __init__(
370425
self.http_client.mount("https://", a)
371426
self.http_client = ThrottledHttpClient(
372427
self.http_client,
373-
{} # Hard code an in-memory cache, for now
428+
{} if http_cache is None else http_cache, # Default to an in-memory dict
374429
)
375430

376431
self.app_name = app_name

0 commit comments

Comments
 (0)