Rails static page caching won't generally work with Java ServletFilter unless 
some serious hack with the cache directory is found
---------------------------------------------------------------------------------------------------------------------------------

                 Key: JRUBY-2832
                 URL: http://jira.codehaus.org/browse/JRUBY-2832
             Project: JRuby
          Issue Type: Bug
          Components: Rails WAR Deployment
    Affects Versions: JRuby 1.1.3
         Environment: JRuby 1.1.3, Ubuntu Hardy Heron, last Java 6, Tomcat 6 or 
Glassfish v2
            Reporter: Raphael Valyi
            Priority: Critical


NB: you don't even need a Rails application to understand why things won't work 
properly. A simple custom ServletFilter logging something when called would 
prove you we need to find an other solution with JRuby-Rack.

So suppose you adhere to Rails Restful conventions (like resources) and you 
have a 'topics' resources for instance.
Then, in a normal Rails application (like served by Mongrel) if you do

POST /topics    -> that creates a new topic using the create method of 
TopicsController
GET /topics       -> that read the topics index and list all the topics, using 
the index method of TopicsController
GET /topics/:id    -> renders the topic with the provided :id using the show 
method in TopicController

Now suppose you want to cache the /topics/:id show page with the cache_page 
:show statement inside your TopicsController
Normally, the first time you request a topic, a /topics/:id.html file will be 
created inside your RAILS_ROOT/public directory. This is true as well when 
deploying as a WAR.
( good explanations about page caching to be found here: 
http://www.railsenvy.com/2007/2/28/rails-caching-tutorial#pagecaching  )

BUT, as soon as the 'topics' directory gets created inside your Java webapp 
RAILS_ROOT/public directory, any attempt to create a new topic will fail, both 
on Tomcat6 and Glassfish v2 at least!

Why? Because at least on those Java servers, if you do;
POST /topics     while a "/topics" directory exists inside your 
RAILS_ROOT/public directory
then the server will answer an empty content with the following HTTP headers:
HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Location: http://localhost:8080/topics/
Transfer-Encoding: chunked
Date: Sun, 20 Jul 2008 00:16:39 GMT


But the thing is that the server answers this without even calling any 
ServletFilter! Also notice that the ServletFilters are usually called even when 
requesting a static content. What screws it up here is the presence of a 
'/topics' directory which isn't a file but matches the request path. Same thing 
happens when performing a GET on paths having a corresponding public directory. 

So the RackFilter isn't even called when doing so. So you have no chance to 
answer properly to the request at all!
You can easily reproduce that behavior with that command line:
>curl -d ""  http://localhost:8080/topics
(try both: with and without a '/topics' directory inside your RAILS_ROOT/public 
directory)


Moreover, to screw things a bit more, using Firefox3 at least, the browser send 
a GET /topics/ after the POST /topics returned a 302 header with the Location: 
http://localhost:8080/topics/ (notice the '/' at the end of the path) . Then 
the GET /topics/ will might be served but that would generally not do what you 
would expect with the POST /topics action. In the Restful case, you'll be 
redirected to the topics list instead of creating a resource!


Since the RackFilter isn't even called, static page caching on Java servers 
won't generally work out of the box.

I see two solutions now:
 1) append '/' at the end of your post (or get) request where there could exist 
a public directory: doing POST /topics/ works while POST /topics will fail. But 
this is not the nice default Rails behavior so you'll need to be hack your POST 
urls in the forms of your Rails application. Not very nice.

2) configure your Rails application to put the cached files elsewhere, like in 
your environment.rb:
config.action_controller.page_cache_directory = RAILS_ROOT + 
"/public/my_cache_path/"
Then, inside the RackFilter, we should prefix request path with the 
my_cache_path inside the maybeAppendHtmlToPath method. I'll try that to see 
were I get.


Hope this helps. Don't hesitate to ask me more details if required. Best 
regards,

Raphaƫl Valyi.


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to