GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Description: Phusion Passenger (mod_rails)
Homepage: http://www.modrails.com/
Clone URL: git://github.com/FooBarWidget/passenger.git
Click here to lend your support to: passenger and make a donation at www.pledgie.com !
Fix page caching for non-GET requests. Add tests for file upload support.
Hongli Lai (Phusion) (author)
Sat Mar 01 12:46:10 -0800 2008
commit  e543369d2f9605052922fb7121c656c67173f55f
tree    d8b07dccc6b27308ac6a9af8ae8344278d9881a0
parent  758b5e251408531d3410dfbe115a5dafaf78107e
...
369
370
371
 
 
372
373
374
...
376
377
378
379
380
 
 
381
382
383
384
 
385
386
387
388
 
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
 
404
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
405
406
407
...
369
370
371
372
373
374
375
376
...
378
379
380
 
 
381
382
383
384
385
 
386
387
388
389
 
390
391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
0
@@ -369,6 +369,8 @@ public:
0
   int
0
   mapToStorage(request_rec *r) {
0
     DirConfig *config = getDirConfig(r);
0
+ bool forwardToRails;
0
+
0
     if (determineRailsBaseURI(r, config) == NULL
0
      || fileExists(r->filename)) {
0
       /*
0
@@ -376,32 +378,48 @@ public:
0
        * If the file already exists, serve it directly.
0
        * This is for static assets like .css and .js files.
0
        */
0
- return DECLINED;
0
- } else {
0
+ forwardToRails = false;
0
+ } else if (r->method_number == M_GET) {
0
       char *html_file = apr_pstrcat(r->pool, r->filename, ".html", NULL);
0
       if (fileExists(html_file)) {
0
         /* If a .html version of the URI exists, serve it directly.
0
- * This is used by page caching.
0
+ * We're essentially accelerating Rails page caching.
0
          */
0
         r->filename = html_file;
0
         r->canonical_filename = html_file;
0
- return DECLINED;
0
+ forwardToRails = false;
0
       } else {
0
- /* Apache's default map_to_storage process does strange
0
- * things with the filename. Suppose that the DocumentRoot
0
- * is /website, on server http://test.com/. If we access
0
- * http://test.com/foo/bar, and /website/foo/bar does not
0
- * exist, then Apache will change the filename to
0
- * /website/foo instead of the expected /website/bar.
0
- * We make sure that doesn't happen.
0
- *
0
- * Incidentally, this also disables mod_rewrite. That is a
0
- * good thing because the default Rails .htaccess file
0
- * interferes with Passenger anyway (it delegates requests
0
- * to the CGI script dispatch.cgi).
0
- */
0
- return OK;
0
+ forwardToRails = true;
0
       }
0
+ } else {
0
+ /*
0
+ * Non-GET requests are always forwarded to Rails.
0
+ * This important because of REST conventions, e.g.
0
+ * 'POST /foo' maps to 'FooController.create',
0
+ * while 'GET /foo' maps to 'FooController.index'.
0
+ * We wouldn't want our page caching support to interfere
0
+ * with that.
0
+ */
0
+ forwardToRails = true;
0
+ }
0
+
0
+ if (forwardToRails) {
0
+ /* Apache's default map_to_storage process does strange
0
+ * things with the filename. Suppose that the DocumentRoot
0
+ * is /website, on server http://test.com/. If we access
0
+ * http://test.com/foo/bar, and /website/foo/bar does not
0
+ * exist, then Apache will change the filename to
0
+ * /website/foo instead of the expected /website/bar.
0
+ * We make sure that doesn't happen.
0
+ *
0
+ * Incidentally, this also disables mod_rewrite. That is a
0
+ * good thing because the default Rails .htaccess file
0
+ * interferes with Passenger anyway (it delegates requests
0
+ * to the CGI script dispatch.cgi).
0
+ */
0
+ return OK;
0
+ } else {
0
+ return DECLINED;
0
     }
0
   }
0
 };
...
3
4
5
 
6
7
8
...
21
22
23
 
 
 
 
24
25
26
...
46
47
48
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
51
52
...
81
82
83
 
84
85
86
...
179
180
181
182
 
 
 
 
 
 
 
 
 
 
183
184
185
...
3
4
5
6
7
8
9
...
22
23
24
25
26
27
28
29
30
31
...
51
52
53
 
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
103
104
105
106
107
108
109
...
202
203
204
 
205
206
207
208
209
210
211
212
213
214
215
216
217
0
@@ -3,6 +3,7 @@ require 'uri'
0
 require 'resolv'
0
 require 'timeout'
0
 require 'support/config'
0
+require 'support/multipart'
0
 require 'support/apache2_config_writer'
0
 require 'passenger/platform_info'
0
 
0
@@ -21,6 +22,10 @@ shared_examples_for "MyCook(tm) beta" do
0
     get('/uploads').should =~ %r{This is the cached version of /uploads}
0
   end
0
   
0
+ it "should not use page caching if the HTTP request is not GET" do
0
+ post('/welcome/cached').should =~ %r{This content should never be displayed}
0
+ end
0
+
0
   it "should not be interfered by Rails's default .htaccess dispatcher rules" do
0
     # Already being tested by all the other tests.
0
   end
0
@@ -46,7 +51,24 @@ shared_examples_for "MyCook(tm) beta" do
0
     result.should =~ %r{Instructions: Call 0900-BANANAPANCAKES}
0
   end
0
   
0
- it "should be possible to upload a file"
0
+ it "should be possible to upload a file" do
0
+ rails_png = File.open("#{@app_root}/public/images/rails.png", 'rb')
0
+ params = {
0
+ 'upload[name1]' => 'Kotonoha',
0
+ 'upload[name2]' => 'Sekai',
0
+ 'upload[data]' => rails_png
0
+ }
0
+ begin
0
+ response = post('/uploads', params)
0
+ rails_png.rewind
0
+ response.should ==
0
+ "name 1 = Kotonoha\n" <<
0
+ "name 2 = Sekai\n" <<
0
+ "data = " << rails_png.read
0
+ ensure
0
+ rails_png.close
0
+ end
0
+ end
0
   
0
   it "should properly handle custom headers" do
0
     response = get_response('/welcome/headers_test')
0
@@ -81,6 +103,7 @@ shared_examples_for "MyCook(tm) beta" do
0
           end
0
         }
0
       end
0
+ sleep(1)
0
       # NOTE: this test might fail when the system is under high load. There
0
       # appears to be some racing condition somewhere.
0
       File.open(restart_file, 'w') do end
0
@@ -179,7 +202,16 @@ describe "mod_passenger running in Apache 2" do
0
   end
0
   
0
   def post(uri, params = {})
0
- return Net::HTTP.post_form(URI.parse("#{@server}#{uri}"), params).body
0
+ url = URI.parse("#{@server}#{uri}")
0
+ if params.values.any? { |x| x.respond_to?(:read) }
0
+ mp = Multipart::MultipartPost.new
0
+ query, headers = mp.prepare_query(params)
0
+ Net::HTTP.start(url.host, url.port) do |http|
0
+ return http.post(url.path, query, headers).body
0
+ end
0
+ else
0
+ return Net::HTTP.post_form(url, params).body
0
+ end
0
   end
0
   
0
   def public_file(name)
...
1
2
 
 
 
 
 
 
 
 
3
...
1
2
3
4
5
6
7
8
9
10
11
0
@@ -1,3 +1,11 @@
0
 class UploadsController < ApplicationController
0
   caches_page :index
0
+
0
+ def create
0
+ headers["Content-Type"] = "text/plain"
0
+ render :text =>
0
+ "name 1 = " + params[:upload][:name1] + "\n" +
0
+ "name 2 = " + params[:upload][:name2] + "\n" +
0
+ "data = " + params[:upload][:data].read
0
+ end
0
 end

Comments

    No one has commented yet.