why spring boot set Expires header to Expires:? - spring

I'm trying to cache control all static css/js files. the codes look like:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/console/*.js","/console/*.css","/console/*.png","/console/*.svg")
.addResourceLocations(
ResourceUtils.CLASSPATH_URL_PREFIX + "/public/console/"
).setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS).cachePublic());
}
I can see the Cache-Control header is correctly set. But why the Expires is always blank ? I'm expecting refresh for all css/js should return 304 Not Modified rather than 200 OK?
Any idea why ? Thanks

The Expires is not needed anymore and recent versions of Spring adopted best practices for front-end caching (see CacheControl and the original commit).
Now if you're not getting the expected result, it might be because your browser is sending a Cache-Control: no-cache request header. This usually happens if you've checked a "disable cache" checkbox in your browser developer tools or if you've refreshed the page with "ctrl+R".
If this is related to Spring Security, you might want to subscribe to this issue and use the following workaround
If not, please provide more information in your question (request and response headers are a good start).

Related

Why isn't redirection based localization working with Blazor Server on Firefox?

We are using dynamically set culture based on cookies and redirection with Blazor Server, with 100% fidelity on the set-up in the documentation with a CultureController:
public IActionResult Set(string culture, string redirectUri)
{
if (culture != null)
{
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture, culture)));
}
return LocalRedirect(redirectUri);
}
With Chromium based browsers and Safari there are no problems: the Set-Cookie header on the response is working great and then the browser is redirected.
With Firefox though, it seems the request to the controller is being aborted for some reason, thus not receiving the Set-Cookie header before the redirection and ultimately not changing the culture:
Here is the same thing on Chrome where the header is working:
I have checked for Cookie attributes (tried everything: Strict, Secure, etc. No luck), if there were any options to add for the LocalRedirect to wait and not cancel other requests.
Any leads would be greatly appreciated.
Edit: Additionnal info (StackTrace of the blocked request)
Seems like the request gets canceled by Blazor SignalR connection reset, which seems to have a timing issue only on Firefox from what I understand (or Firefox treats it differently somehow).

Prevent Google Chrome from sending Sec-Fetch headers

I would like to cache static content (index.html) in my web API 2 (net. framework 4.6.2 app)
I wrote OWIN middleware that adds a cache-control header to the response, allowing for subsequent requests to be retrieved from the browser cache.
The OWIN context extension:
public static class BrowserCacheOwinContextExtensions {
public static IOwinContext SetCacheControlHeader(this IOwinContext context, int maxAge) {
context.Response.Headers["Cache-Control"] = $"public, max-age={maxAge}";
context.Response.Headers["Vary"] = "User-Agent";
return context;
}
}
Snippet from middleware:
if (browserCacheOptions.IsEnable) {
context.SetCacheControlHeader(browserCacheOptions.MaxAge);
}
await context.Response.WriteAsync(file);
It works fine in the Mozilla browser but doesn't in Chrome.
Snippet from Mozilla:
I believe the root cause of this is that Chrome adds additional Sec-Fetch headers + cache-control: max-age=0 to the request automatically.
Automatically added Sec-Fetch headers by Chrome:
Note: if open the same request at separate browser tab it works fine ever for Chrome (no sec-fetch headers in request)
Q: Is it possible to somehow disable such behaviour and don't add sec-fetch headers automatically to the request?
Or if you have other proposals, please do share them.
You cannot modify the sec- as it is in forbidden headers list.
This basically a list of headers that cannot be modified using the client side scripting.

ASP.NET MVC Page with ResponseCache on action DOES return new content instead of cache

I followed this tutorial (https://learn.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-2.1) to implement ResponseCache on my controller-action.
In short, I added
services.AddResponseCaching(); and app.UseResponseCaching(); in the startup and this tag [ResponseCache( Duration = 30)] on my controller.
Then I added a <h2>#DateTime.Now</h2> in my view and what I expected.... was the same datetime.now for 30 seconds.
But it doesn't, it just shows the new time on every reload (F5).
I made sure my devtools in chrome do not say 'disable cache'.
It's both with and without the chrome devtools open, on my local machine, now trying on a brandnew .net core mvc project.
One thing I noticed (with devtools open) is that the request has this header: Cache-Control: max-age=0. Does this influence the behaviour?
I thought it would mean something because it looks like the request says 'no cache' but that strikes me as weird because I didn't put the header in and I would say the default behaviour of chrome wouldn't be to ignore caches?
A header like Cache-Control: max-age=0 effectively disables all caching. Resources are basically expired as soon as they come off the wire, so they are always fetched. This header originates from the server. The client has nothing to do with it.
Assuming you haven't disabled response caching manually in some way by accident. Then, the most likeliest situation is that you're doing something where the response caching middleware will never cache. The documentation lists the following conditions that must be satisfied before responses will be cached, regardless of what you do:
The request must result in a server response with a 200 (OK) status code.
The request method must be GET or HEAD.
Terminal middleware, such as Static File Middleware, must not process the response prior to the Response Caching Middleware.
The Authorization header must not be present.
Cache-Control header parameters must be valid, and the response must be marked public and not marked private.
The Pragma: no-cache header must not be present if the Cache-Control header isn't present, as the Cache-Control header overrides the Pragma header when present.
The Set-Cookie header must not be present.
Vary header parameters must be valid and not equal to *.
The Content-Length header value (if set) must match the size of the response body.
The IHttpSendFileFeature isn't used.
The response must not be stale as specified by the Expires header and the max-age and s-maxage cache directives.
Response buffering must be successful, and the size of the response must be smaller than the configured or default SizeLimit.
The response must be cacheable according to the RFC 7234 specifications. For example, the no-store directive must not exist in request or response header fields. See Section 3: Storing Responses in Caches of RFC 7234 for details.
However, in such situations, the server should be sending Cache-Control: no-cache, not max-age=0. As a result, I'm leaning towards some misconfiguration somewhere, where you have set this max age value and either forgot or overlooked it.
This is working for me in a 3.1 app to not let F5/Ctrl+F5 or Developer Tools in Firefox or Chrome bypass server cache for a full response.
In startup add this little middleware before UseResponseCaching().
// Middleware that fixes server caching on F5/Reload
app.Use(async (context, next) =>
{
const string cc = "Cache-Control";
if (context.Request.Headers.ContainsKey(cc))
{
context.Request.Headers.Remove(cc);
}
const string pragma = "Pragma";
if (context.Request.Headers.ContainsKey(pragma))
{
context.Request.Headers.Remove(pragma);
}
await next();
});
app.UseResponseCaching();
Haven't noticed any problems...

Force chrome to cache static content like images

I want to improve my experience with the internet by caching static content like images(jpg,png,gif) and fonts. Because always happens that when watching a webpage with a lot of images, and then I refresh with F5, the same contents are downloaded again.
I know that it's because the response headers could contain no cache o max-age 0, and even sometimes it happens when there is no cache o max-age in the response.
But in case of images or fonts that never change, it's useless to get max-age 0. So I wanted to know if there is a way to override the response headers and set them with max-age 1 year. Maybe with a chrome extension?
Yes you can do this by using a Chrome Extension. See this Change HTTP Headers chrome extension already does it.
For your specific case, you just need to do this:
Add an event listener which should be called whenever headers are received.
Read the details of the headers
Check if response content type is image
Add/Update the desired header to the headers
To accomplish this you can use webRequest Headers Received event.
Documentation of onHeadersReceived
onHeadersReceived (optionally synchronous): Fires each time that an HTTP(S) response header is received. Due to redirects and authentication requests this can happen multiple times per request. This event is intended to allow extensions to add, modify, and delete response headers, such as incoming Set-Cookie headers.
Your code will look something like this
chrome.webRequest.onHeadersReceived.addListener(function(details){
for(var i = 0; i < details.responseHeaders.length; i++) {
// If response is of image, add the cache-control header
}
return {responseHeaders: details.responseHeaders};
},
{urls: ['https://*/*'], types: ['image'] },
['blocking', 'responseHeaders']);
PS: I have not run and tested the code so please excuse the typos.
EDIT (After #RobW comment)
No, this is not possible as of now (22 march 2014). Adding Cache-control has no influence on the caching behavior. Check out this answer for more details.
Albeit this is an old question, I stumbled upon it recently. Later I found the chrome extension "Speed-Up Browsing" which seems to do exactly what the OP asked for.
For me it worked.
https://chrome.google.com/webstore/detail/speed-up-browsing/hkhnldpdljhiooeallkmlajnogjghdfb?hl=en
You could use Fiddle https://www.telerik.com/fiddler (free) as proxy adding caching for selected URLs or patterns. I did that a

Serving content depending on http accept header - caching problems?

I'm developing an application which is supposed to serve different content for "normal" browser requests and AJAX requests for the same URL requested.
(in fact, encapsulate the response HTML in JSON object if the request is AJAX).
For this purpose, I'm detecting an AJAX request on the server side, and processing the response appropriately, see the pseudocode below:
function process_response(request, response)
{
if request.is_ajax
{
response.headers['Content-Type'] = 'application/json';
response.headers['Cache-Control'] = 'no-cache';
response.content = JSON( some_data... )
}
}
The problem is that when the first AJAX request to the currently viewed URL is made strange things happens on Google Chrome - if, right after the response comes and is processed via JavaScript, user clicks some link (static, which redirects to other page) and then clicks back button in the browser, he sees the returned JSON code instead of the rendered website (logging the server I can say that no request is made). It seems for me that Chrome stores the latest request response for the specific URL, and doesn't take into account that it has different content-type etc.
Is that a bug in the Chrome or am I misusing HTTP protocol ?
--- update 12 11 2012, 12:38 UTC
following PatrikAkerstrand answer, I've found following Chrome bug: http://code.google.com/p/chromium/issues/detail?id=94369
any ideas how to avoid this behaviour?
You should also include a Vary-header:
response.headers['Vary'] = 'Content-Type'
Vary is a standard way to control caching context in content negotiation. Unfortunately it has also buggy implementations in some browsers, see Browser cache vary broken.
I would suggest using unique URLs.
Depending of you framework capabilities you can redirect (302) the browser to URL + .html to force response format and make cache key unique within browser session. Then for AJAX requests you can still keep suffix-less URL. Alternatively you may suffix AJAX URL with .json instead .
Another options are: prefixing AJAX requests with /api or adding some cache boosting query params ?rand=1234.
Setting cache-control to no-store made it in my case, while no-cache didn't. This may have unwanted side effects though.
no-store: The response may not be stored in any cache. Although other directives may be set, this alone is the only directive you need in preventing cached responses on modern browsers.
Source: Mozilla Developer Network - HTTP Cache-Control

Resources