Merge pull request #26737 from blaggacao/feat/cache-control
feat: add cache control
This commit is contained in:
commit
1214763b25
5 changed files with 38 additions and 9 deletions
|
|
@ -8,6 +8,7 @@ import os
|
|||
import re
|
||||
|
||||
from werkzeug.exceptions import HTTPException, NotFound
|
||||
from werkzeug.http import generate_etag, is_resource_modified, quote_etag
|
||||
from werkzeug.middleware.profiler import ProfilerMiddleware
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
from werkzeug.middleware.shared_data import SharedDataMiddleware
|
||||
|
|
@ -148,8 +149,13 @@ def application(request: Request):
|
|||
# We can not handle exceptions safely here.
|
||||
frappe.logger().error("Failed to run after request hook", exc_info=True)
|
||||
|
||||
log_request(request, response)
|
||||
process_response(response)
|
||||
log_request(request, response)
|
||||
# return 304 if unmodified
|
||||
if not response.direct_passthrough:
|
||||
etag = generate_etag(response.data)
|
||||
if not is_resource_modified(request.environ, etag):
|
||||
return Response(status=304, headers={"ETag": quote_etag(etag)})
|
||||
process_response(response)
|
||||
|
||||
return response
|
||||
|
||||
|
|
@ -237,8 +243,26 @@ def process_response(response):
|
|||
if not response:
|
||||
return
|
||||
|
||||
# set cookies
|
||||
if hasattr(frappe.local, "cookie_manager"):
|
||||
# cache control
|
||||
# read: https://simonhearne.com/2022/caching-header-best-practices/
|
||||
if frappe.local.response.can_cache:
|
||||
response.headers.extend(
|
||||
{
|
||||
# default: 5m (proxy), 5m (client), 3h (allow stale resources for this long if upstream is down)
|
||||
"Cache-Control": "public,s-maxage=300,max-age=300,stale-while-revalidate=10800",
|
||||
# for revalidation of a stale resource
|
||||
"ETag": quote_etag(generate_etag(response.data)),
|
||||
}
|
||||
)
|
||||
else:
|
||||
response.headers.extend(
|
||||
{
|
||||
"Cache-Control": "no-store,no-cache,must-revalidate,max-age=0",
|
||||
}
|
||||
)
|
||||
|
||||
# Set cookies, only if response is non-cacheable to avoid proxy cache invalidation
|
||||
if hasattr(frappe.local, "cookie_manager") and not frappe.local.response.can_cache:
|
||||
frappe.local.cookie_manager.flush_cookies(response=response)
|
||||
|
||||
# rate limiter headers
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ class HTTPRequest:
|
|||
|
||||
|
||||
class LoginManager:
|
||||
__slots__ = ("user", "info", "full_name", "user_type", "resume")
|
||||
__slots__ = ("user", "info", "full_name", "user_type", "user_lang", "resume")
|
||||
|
||||
def __init__(self):
|
||||
self.user = None
|
||||
|
|
@ -161,7 +161,7 @@ class LoginManager:
|
|||
self.info = frappe.get_cached_value(
|
||||
"User", self.user, ["user_type", "first_name", "last_name", "user_image"], as_dict=1
|
||||
)
|
||||
|
||||
self.user_lang = frappe.translate.get_user_lang()
|
||||
self.user_type = self.info.user_type
|
||||
|
||||
def setup_boot_cache(self):
|
||||
|
|
@ -198,6 +198,8 @@ class LoginManager:
|
|||
frappe.local.cookie_manager.set_cookie("full_name", self.full_name)
|
||||
frappe.local.cookie_manager.set_cookie("user_id", self.user)
|
||||
frappe.local.cookie_manager.set_cookie("user_image", self.info.user_image or "")
|
||||
# cache control: round trip the effectively delivered language
|
||||
frappe.local.cookie_manager.set_cookie("user_lang", self.user_lang)
|
||||
|
||||
def clear_preferred_language(self):
|
||||
frappe.local.cookie_manager.delete_cookie("preferred_language")
|
||||
|
|
@ -418,7 +420,9 @@ def get_logged_user():
|
|||
def clear_cookies():
|
||||
if hasattr(frappe.local, "session"):
|
||||
frappe.session.sid = ""
|
||||
frappe.local.cookie_manager.delete_cookie(["full_name", "user_id", "sid", "user_image", "system_user"])
|
||||
frappe.local.cookie_manager.delete_cookie(
|
||||
["full_name", "user_id", "sid", "user_image", "user_lang", "system_user"]
|
||||
)
|
||||
|
||||
|
||||
def validate_ip_address(user):
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ frappe.request.call = function (opts) {
|
|||
},
|
||||
opts.headers
|
||||
),
|
||||
cache: true,
|
||||
cache: window.dev_server ? false : true,
|
||||
};
|
||||
|
||||
if (opts.args && opts.args.doctype) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,5 @@ class RedirectPage:
|
|||
self.http_status_code,
|
||||
{
|
||||
"Location": frappe.flags.redirect_location or (frappe.local.response or {}).get("location"),
|
||||
"Cache-Control": "no-store, no-cache, must-revalidate",
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -523,6 +523,7 @@ def cache_html(func):
|
|||
html = page_cache[frappe.local.lang]
|
||||
if html:
|
||||
frappe.local.response.from_cache = True
|
||||
frappe.local.response.can_cache = True
|
||||
return html
|
||||
html = func(*args, **kwargs)
|
||||
context = args[0].context
|
||||
|
|
@ -530,6 +531,7 @@ def cache_html(func):
|
|||
page_cache = frappe.cache.hget("website_page", args[0].path) or {}
|
||||
page_cache[frappe.local.lang] = html
|
||||
frappe.cache.hset("website_page", args[0].path, page_cache)
|
||||
frappe.local.response.can_cache = True
|
||||
|
||||
return html
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue