Enable Grails application to serve resources through CDN
In a recent project we were required to move our static content files to some CDN because servers were getting millions of hits every hour and many of the resources on the main page were static (like JS/CSS/etc). I hope most of the people understand CDN already. So, I’m not covering any information on CDN fundamentals or how to set it up.
In this post, I am just mentioning the highlights and important points in context to a Grails application considering security issues.
Changes around “Resources” plugin.
I know there are alternates too (like asset-pipeline), but we were using resources plugin already.
- We need to setup and enable the baseurl – see the following configs.
grails.resources.mappers.baseurl.enabled = true
grails.resources.mappers.baseurl.default = "http://xxx.cloudfront.net/app/static"
grails.resources.mappers.baseurl.default is the base URL to your CDN server, as you can see AWS CloudFront link is used for the CDN service. You can configure multiple servers for serving the different modules. Here’s a link for baseurl mappers.
Ensure that the following config is either commented out or turned off
[code]grails.resources.debug = false[/code]
This is very important – it will let the resources plugin generate a dynamic link using hash of the resource’s content. Let’s say you redeploy the build with changes in a file’s content, so this will be treated as a different file and CDN’s older cache won’t come into the picture.
Grails resources plugin already handles the cache headers in a very mature way, so as a good practice you can always configure your CDN to use the response headers only for the caching strategy (at the CDN side). In case you have some very special requirement you can configure your CDN differently.
Ensure that following config is all set (in case you want different types of resources to be processed through CDN/resources plugin).
grails.resources.adhoc.patterns =["/images/*", "*.css", "*.js","*.swf"]
- If you are using secure pages (HTTPS), you will need to setup the SSL certificate at the CDN side.
In case you face any cross domain issues for loading some resources, you can install CORS plugin. https://grails.org/plugin/cors
cors.url.pattern = [‘/static/*’]
In case Spring security plugin is setup
Following will let the security plugin bypass the responses if resource/page NOT FOUND (404).
grails.plugins.springsecurity.rejectIfNoRule = false
// following is true by default, so not required
grails.plugin.springsecurity.fii.rejectPublicInvocations = true
This is very important step to ensure your Grails application will send 404 response code when a requested page/resources was not found. Otherwise, (depending upon your default settings) – you may receive login page with 200 status code. So you can understand the ultimate bad effects of this thing.
The above changes are suggested on a personal discretion and learning that I’ve had from the recent work – however it might not fit into all the use cases. I hope it will help you. 🙂