how to avoid reloading js and css in jsp - java

I have few same js and css files and i used to load from different jsps.
If already css and js loaded, we need to not load files again.
But those files are reloading. And giving 200 Success code in firebug console.
it should give 302 success code
i can hit the url directly. I dont want to call js and css dynamically.
load the jsp content
css and js loading done through relative path. i couldnt copy the code. Because it is not allowing here
If any additional information require, pls update

Assuming that you are referencing the CSS and JS files from your JSPs as static references in <script> and <link> tags, you can avoid the scenario where the browser is provided with these files on every request by setting HTTP headers when you first serve them.
Without setting appropriate expiration times or "freshness" guarantees for resources, browsers will typically end up issuing for a fresh copy of the resource every time, even though the resource may be present in the browse cache. Note, that if the browser cache is disabled, then you cannot, as a web-programmer do anything about the browser's behavior, unless you get your users to enable the browser cache; until then, the browser will request for fresh copies of resources every single time. These requests may be served by a proxy cache, but it is not necessary that such a cache exist.
Setting resource expiration times or freshness guarantees in Java web applications can be accomplished by either of the following:
Configuring the HTTP server, or the Web Application server (if that is possible) to set Expires and Cache-Control headers in the HTTP responses generated for the CSS and JS files or mimetypes. Configuration changes that ought to be done would vary from server to server and are too expansive to list here.
Writing a Servlet filter for your web application that will intercept all responses for URLs ending with *.js and *.css and add HTTP Expires and Cache-Control headers to the responses. This option is less preferable especially if you wish to have the same amount of configurability that is afforded by web and application servers; you will need to provide any configuration options via init parameters for the filter in your web.xml file. Also, changes to the configuration will require a restart of the application containing the filter.
If you need to understand the values to be specified for the Expires and Cache-Control headers, then I would recommend that you read the "Caching Tutorial for Web Authors and Webmasters", which provides details on how to use the Expires and Cache-Control headers and how they affect caching behavior.
Suggested values for the expiration times specified in the Expires header or the max-age value in the Cache-Control header, range from a few minutes to a few hours, depending on how often you change the site content. You must also avoid specifying Cache-Control headers with no-cache and no-store values, for they would often end up issuing requests for the same resource on the next attempt.

Related

GWT - Prevent PDF file from being cached in IE?

I have a GWT Web App (which requires a login) that calls a method on the Servlet (running in Tomcat) to generate a PDF file. The Servlet returns a URL to the file and opens the PDF in an iFrame.
Frame frame = new Frame(reportUrl);
frame.show();
Upon closing the frame (or browser), a request is made to delete the file that was generated server side. Now here is where the problem lies. If I log out of the web application, and open a new tab in IE, it shows the URL in the history that was used to display the PDF. Ideally this file is no longer accessible since it has been deleted on the server, and the user is no longer logged in, however the PDF still displays in the new tab. I assume this is because the PDF file is being cached.
I am unable to reproduce this behavior in Chrome, so I assume the file either isn't being cached in Chrome, or Chrome just handles things a little differently. Long story short, how do I make sure the file/url is no longer accessible once the user logs out of the web app?
Theoretically this is impossible, as you can't remotely clear the client-side cache. Also the user may have used wget or whatever to download the file so you can't assume information will be 100% inaccessible after the session has expired.
That being said, caching hints in the HTTP response headers can to some extent steer what a (well-behaved) client caches. As always implementation differs accross browsers. You can set HTTP headers either from your servlet directly in Java, or you can add them for instance from Apache HTTPD specifying cache headers for instance for all PDF downloads.
There are many resources on cache headers in HTTP, here's a good one: http://www.mobify.com/blog/beginners-guide-to-http-cache-headers/
I've also seen that HTTPS connections cause IE to be much stricter in what it caches, not sure if that is relevant/an option for you.

JavaScript and CSS files are cached by the browser by default?

As per my understanding files are cached by the browser by default. Developers don't have to set specific
headers to enable the caching of these files. Right?
If yes, how come browser know that it has to enable caching for specific types of files only not for servlet/jsp calls. For example :- if i make call to same servlet
request goes to server side and fresh page is served (not the browser cached paged).

Changes in HTML not reflected as long as I am using proxy

I shifted from Eclipse to Jdeveloper. I had a weird problem that I was able to solve but not able to understand.
Whenever I made any changes in HTML in Jdeveloper's web projects the changes were not reflected when I ran the HTML again. The old webpages kept coming in the webbrowser. Same source code. Same CSS/JS. I found that as long as there were proxy settings in my web browser the changes were not reflected. But if I switched off the proxy the changes made in HTML were reflected i.e webpage were displayed with the changes made from last time.
By proxy set I mean proxy setting placed at the following
Window -> Start Menu -> internet options -> Connections -> LAN Settings -> Proxy Server
I have tried to run the resulting URL on Google chrome, Firefox and internet explorer. As long as the web browser was using proxy the changes made in HTML were not shown by running it again.
In Eclipse Juno I simply had to clean Tomcat's directory to get changes reflected.
Anyone can explain why this happens?
Web servers return HTTP headers with every response, and usually those headers specify how long the response can be cached for. Proxy servers read those headers and make a decision whenever they see the same request again -- whether to propagate that request to the server again, or to simply return the cached copy of the response.
You can modify your server's configuration so that it the next time it tells the proxy server not to cache pages. However, some proxy servers are mis-configured or broken, and will cache pages that they are not supposed to cache.
For those cases, one ugly solution that works is to give your JS and CSS files new names whenever you change them. For example, if your index.html file includes index.css and index.js, and you make a change to index.js, you can save the changed file as index.2.js and change the tag in your index.html file to point to index.2.js from now on.
That's a bit drastic, but it works. A simpler solution to start with is to refresh your page using Shift-F5 rather than just F5 (in your browser). That tells the browser to force a refresh of all cached pages, whenever possible.
This seems tied to your proxy server type. There are several proxy server types, one of which is a "Caching Proxy Server". Which, if many users are connected to it, allows static pages to be stored locally on the server for repetitive requests from the client(you). When you change the proxy it is most likely just sending you an updated copy due to not having you as an active client, or being that you are a new user.
I would assume that the content on the new software you are building is precaching saved page names where as Eclipse Juno is was generating real time screens on the fly, bypassing the cached server option.

The Case of The Mysterious Content-Disposition Header

Our product includes a Flash application that is loaded by SWFObject. For one customer, when accessing this SWF via HTTPS (but not HTTP), Flash Player will not load it.
I asked the customer to go directly to the URL of the SWF file (rather than the wrapper page):
When he does so via HTTP, the SWF loads in the browser.
When he does so via HTTPS, IE7 presents him with a 'save file' dialog box. This implies that a "Content-Disposition: attachment" header is present in the response. That would also explain why the SWF isn't loading in Flash Player: as a security measure, it will not play SWFs served with that header.
So, I have a couple of things I'm trying to figure out:
How can I be certain that a Content-Disposition header is being sent by the server (rather than it being a strange artifact of IE7)? The user only has IE7 at his disposal, and cannot use Firefox, Chrome, etc. IE7 doesn't include the handy 'Network' tab that's present in IE9's developer tools.
Assuming that the header is present, how is it getting there? They are running Tomcat 6. The SWF is being served by Tomcat's default servlet. The header appears to be present if the HTTPS connector is used, but not if the HTTP connector is used. The Tomcat configuration is stock except for enabling the HTTPS connector.
On a side note, I don't trust Flash's cache clearing. On my machine under IE9, the SWF is often satisfied by cache even after I explicitly clear the browser cache and Flash Player's stored data: I don't see any request for it in Fiddler, or in Tomcat's access logs, but the SWF loads in the browser. Am I missing something here? Could the customer be accessing some bogus cached version of the SWF?
Edit: Apparently the 'clear cache' command in the developer tools doesn't really clear the cache. Using the standard method yielded the expected results.
Edit 2: Tracing within Tomcat indicates that the Content-Disposition header is not set. I don't know for certain that it's not being received by the browser, but AFAIK the browser is connecting directly to Tomcat. This seems like an odd browser-side behavior.
The issue had to do with presence of the following headers in the response:
Cache-Control: no-cache
Pragma: no-cache
These were being sent by Tomcat because the page was being protected by a security constraint (configured in conf/web.xml). These headers caused IE7 to act just like a 'Content-Disposition: attachment' header was present.
My solution was to have the customer add the following configuration to Tomcat's conf/context.xml:
<Valve className="org.apache.catalina.authenticator.BasicAuthenticator" securePagesWithPragma="false" />
This replaces the headers with:
Cache-Control: private
...which should still fulfill the goal of preventing proxies from caching the page, while working around IE's issues. This was based on the solution found here:
http://daveharris.wordpress.com/2007/07/09/how-to-configure-cache-control-in-tomcat/
However, that very-similar solution suppressed the headers entirely. Details of these attributes can be found in Tomcat docs here:
http://tomcat.apache.org/tomcat-6.0-doc/config/valve.html#Basic_Authenticator_Valve/Attributes
You should be able to log the outgoing HTTP responses on the server side before encryption, use the null cypher, or provide the RSA keys to wireshark and look at the headers from a packet capture.

Best way for allowing subdomain session cookies using Tomcat

By default tomcat will create a session cookie for the current domain.
If you are on www.example.com, your cookie will be created for www.example.com (will only work on www.example.com). Whereas for example.com it will be created for .example.com (desired behaviour, will work on any subdomain of example.com as well as example.com itself).
I've seen a few Tomcat valves which seem to intercept the creation of session cookies and create a replacement cookie with the correct .example.com domain, however none of them seem to work flawlessly and they all appear to leave the existing cookie and just create a new one. This means that two JSESSIONID cookies are being sent with each request.
I was wondering if anybody has a definitive solution to this problem.
This is apparently supported via a configuration setting in 6.0.27 and onwards:
Configuration is done by editing
META-INF/context.xml
<Context
sessionCookiePath="/something"
sessionCookieDomain=".domain.tld" />
https://issues.apache.org/bugzilla/show_bug.cgi?id=48379
I have just gone through all of this looking for a simple solution. I started looking at it from the tomcat perspective first.
Tomcat does not give direct access to configuring the domain cookie for the session, and I definitely did not want to custom patch tomcat to fix that problem as shown in some other posts.
Valves in tomcat also seems to be a problem solution due to the limitations on accessing headers & cookies built into the Servlet specification. They also fail completely if the http response is commited before it gets passed to your valve.
Since we proxy our requests through Apache, I then moved onto how to use apache to fix the problem instead.
I first tried the mod_proxy directive ProxyPassReverseCookieDomain, but it does not work for JSESSIONID cookies because tomcat does not set the domain attribute and ProxyPassReverseCookieDomain cannot work without some sort of domain being part of the cookie.
I also came across a hack using ProxyPassReverseCookiePath where they were rewriting the path to add a domain attribute to the cookie, but that felt way to messy for a production site.
I finally got it to work by rewriting the response headers using the mod_headers module in apache as mentioned by Dave above.
I have added the following line inside the virtual host definition:
Header edit Set-Cookie "(JSESSIONID\s?=[^;,]+?)((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(;\s?(?:(?i)Domain\s?=)[^;,]+?)?((?:;\s?(?:(?i)Comment|Max-Age|Path|Version|Secure)[^;,]*?)*)(,|$)" "$1$2; Domain=.example.com$4$5"
The above should all be a single line in the config. It will replace any JSESSIONID cookies domain attribute with ".example.com". If a JSESSIONID cookie does not contain a domain attribute, then the pattern will add one with a value of ".example.com". As a bonus, this solution does not suffer from the double JSESSION cookies problem of the valves.
The pattern should work with multiple cookies in the Set-Cookie header without affecting the other cookies in the header. It should also be modifiable to work with other cookies by changing JSESSIONID in the first part of the pattern to what ever cookie name you desire.
I am not reg-ex power user, so I am sure there are a couple of optimisations that could be made to the pattern, but it seems to be working for us so far.
I will update this post if I find any bugs with the pattern. Hopefully this will stop a few of you from having to go through the last couple of days worth of frustrations as I did.
As a session (and its Id) is basically considered of value only for the issueing application, you may rather look for setting an additional cookie. Have a look at Tomcats SingleSignOnValve, providing the extra-Cookie JSESSIONIDSSO (note the ...SSO) for the server path "/" instead of "/applicationName" (as JSESSIONID cookies are usually set).
With such a Valve you may implement any interprocess communication you need in order to synchronize any state between different servers, virtual hosts or webapps on any number of tomcats/webservers/whatever.
Another reason why you cannot use tomcats session cookie for your own purposes is, that multiple webapps on the same host have different session ids. E.g. there are different cookies for "/webapp1" and "/webapp2". If you provide "/webapp1"'s cookie to "/webapp2", this wouldn't find the session you referenced, invalidate your session+cookie and set its own new one. You'd have to rewrite all of tomcats session handling to accept external session id values (bad idea securitywise) or to share a certain state among applications.
Session handling should be considered the containers (tomcats) business. Whatever else you need you should add without interfering with what the container believes is necessary to do.
I've run into this at $DAYJOB. In my case I wanted to implement SSL signon then redirect to a non SSL page. The core problem in tomcat is the method (from memory) SessionManager.configureSessionCookie which hard codes all the variables you would like to get access to.
I came up with a few ideas, including a particularly egregious hack using mod_headers in apache to rewrite the cookie based on regex substitution.
The definative way to solve this would be to submit a patch to the tomcat developers that adds configurable parameters to the SessionManager class.
The valve techniques do not seem to be 100% perfect. If you dare to modify Tomcat itself:
catalina.jar contains the following class: org.apache.catalina.connector.Request
The Request has a method:
configureSessionCookie(Cookie cookie)
For our environment it was best to just hardcode it, but you could do more fancy logic:
cookie.setDomain(".xyz.com");
Seems to work perfectly. Would be nice if this was configurable in tomcat.

Categories

Resources