Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix support for mod_rewrite passthrough rules (issue #230) and fix so…

…me WSGI compliance issues (issue #360).
  • Loading branch information...
commit caa9fd7626761b2f3421012a6a9ed86f9b200d9d 1 parent 7ec85d7
Hongli Lai FooBarWidget authored
19 NEWS
View
@@ -10,6 +10,21 @@ Release 2.2.5
until a timeout occurs. In order to solve this problem, Phusion Passenger
now buffers small file upload in memory. Bug #356.
+ * [Apache] Fixed support for mod_rewrite passthrough rules
+ mod_rewrite passthrough rules were not properly supported because of a bug
+ fix for supporting encoded slashes (%2f) in URLs. Unfortunately, due to
+ bugs/limitations in Apache, we can support either encoded slashes or
+ mod_rewrite passthrough rules, but not both; supporting one will break the
+ other.
+
+ Support for mod_rewrite passthrough rules is now enabled by default; that
+ is, support for encoded slashes is disabled by default. A new configuration
+ option, "PassengerAllowEncodedSlashes", has been added. Turning this option
+ on will enable support for encoded slashes and disable support for
+ mod_rewrite passthrough rules.
+
+ Issue #113 and issue #230.
+
* [Apache] Added a configuration option for resolving symlinks in the document
root path Phusion Passenger 2.2.0 and higher no longer resolve symlinks in
the document root path in order to properly support Capistrano-style
@@ -94,6 +109,10 @@ Release 2.2.5
Bug #359.
+ * Fixed a few bugs in WSGI compliance
+ PATH_INFO is supposed to be set to the request URI, but without the query
+ string and without the base URI. This has been fixed: bug #360.
+
* The Users Guide for Apache now mentions something about correct permissions
for application directories.
* Fixed compilation problems on IA-64 (bug #118). We also reduced the stack
229 doc/Users guide Apache.txt
View
@@ -678,21 +678,6 @@ Example:
</VirtualHost>
-----------------------------
-[[PassengerResolveSymlinksInDocumentRoot]]
-=== PassengerResolveSymlinksInDocumentRoot <on|off> ===
-Configures whether Phusion Passenger should resolve symlinks in the document root.
-Please refer to <<application_detection,How Phusion Passenger detects whether a
-virtual host is a web application>> for more information.
-
-This option may occur in the following places:
-
- * In the global server configuration.
- * In a virtual host configuration block.
- * In a `<Directory>` or `<Location>` block.
- * In '.htaccess', if `AllowOverride Options` is on.
-
-In each place, it may be specified at most once. It is off by default.
-
[[PassengerUseGlobalQueue]]
=== PassengerUseGlobalQueue <on|off> ===
Turns the use of global queuing on or off.
@@ -725,77 +710,6 @@ applications must run as, if user switching fails or is disabled.
This option may only occur once, in the global server configuration.
The default value is 'nobody'.
-[[PassengerHighPerformance]]
-=== PassengerHighPerformance <on|off> ===
-By default, Phusion Passenger is compatible with mod_rewrite and most other
-Apache modules. However, a lot of effort is required in order to be compatible.
-If you turn 'PassengerHighPerformance' to 'on', then Phusion Passenger will be
-a little faster, in return for reduced compatibility with other Apache modules.
-
-In places where 'PassengerHighPerformance' is turned on, mod_rewrite rules will
-likely not work. mod_autoindex (the module which displays a directory index)
-will also not work. Other Apache modules may or may not work, depending on what
-they exactly do. We recommend you to find out how other modules behave in high
-performance mode via testing.
-
-This option is *not* an all-or-nothing global option: you can enable high
-performance mode for certain virtual hosts or certain URLs only.
-The 'PassengerHighPerformance' option may occur in the following places:
-
- * In the global server configuration.
- * In a virtual host configuration block.
- * In a `<Directory>` or `<Location>` block.
- * In '.htaccess'.
-
-In each place, it may be specified at most once. The default value is 'off',
-so high performance mode is disabled by default, and you have to explicitly
-enable it.
-
-.When to enable high performance mode?
-
-If you do not use mod_rewrite or other Apache modules then it might make
-sense to enable high performance mode.
-
-It's likely that some of your applications depend on mod_rewrite or other
-Apache modules, while some do not. In that case you can enable high performance
-for only those applications that don't use other Apache modules. For example:
-
-------------------------------------
-<VirtualHost *:80>
- ServerName www.foo.com
- DocumentRoot /apps/foo/public
- .... mod_rewrite rules or options for other Apache modules here ...
-</VirtualHost>
-
-<VirtualHost *:80>
- ServerName www.bar.com
- DocumentRoot /apps/bar/public
- PassengerHighPerformance on
-</VirtualHost>
-------------------------------------
-
-In the above example, high performance mode is only enabled for www.bar.com.
-It is disabled for everything else.
-
-If your application generally depends on mod_rewrite or other Apache modules,
-but a certain URL that's accessed often doesn't depend on those other modules,
-then you can enable high performance mode for a certain URL only. For example:
-
-------------------------------------
-<VirtualHost *:80>
- ServerName www.foo.com
- DocumentRoot /apps/foo/public
- .... mod_rewrite rules or options for other Apache modules here ...
-
- <Location /chatroom/ajax_update_poll>
- PassengerHighPerformance on
- </Location>
-</VirtualHost>
-------------------------------------
-
-This enables high performance mode for
-http://www.foo.com/chatroom/ajax_update_poll only.
-
=== PassengerEnabled <on|off> ===
You can set this option to 'off' to completely disable Phusion Passenger for
a certain location. This is useful if, for example, you want to integrate a PHP
@@ -1070,6 +984,149 @@ This option may occur in the following places:
In each place, it may be specified at most once. The default value is '0'.
+[[PassengerHighPerformance]]
+==== PassengerHighPerformance <on|off> ====
+By default, Phusion Passenger is compatible with mod_rewrite and most other
+Apache modules. However, a lot of effort is required in order to be compatible.
+If you turn 'PassengerHighPerformance' to 'on', then Phusion Passenger will be
+a little faster, in return for reduced compatibility with other Apache modules.
+
+In places where 'PassengerHighPerformance' is turned on, mod_rewrite rules will
+likely not work. mod_autoindex (the module which displays a directory index)
+will also not work. Other Apache modules may or may not work, depending on what
+they exactly do. We recommend you to find out how other modules behave in high
+performance mode via testing.
+
+This option is *not* an all-or-nothing global option: you can enable high
+performance mode for certain virtual hosts or certain URLs only.
+The 'PassengerHighPerformance' option may occur in the following places:
+
+ * In the global server configuration.
+ * In a virtual host configuration block.
+ * In a `<Directory>` or `<Location>` block.
+ * In '.htaccess'.
+
+In each place, it may be specified at most once. The default value is 'off',
+so high performance mode is disabled by default, and you have to explicitly
+enable it.
+
+.When to enable high performance mode?
+
+If you do not use mod_rewrite or other Apache modules then it might make
+sense to enable high performance mode.
+
+It's likely that some of your applications depend on mod_rewrite or other
+Apache modules, while some do not. In that case you can enable high performance
+for only those applications that don't use other Apache modules. For example:
+
+------------------------------------
+<VirtualHost *:80>
+ ServerName www.foo.com
+ DocumentRoot /apps/foo/public
+ .... mod_rewrite rules or options for other Apache modules here ...
+</VirtualHost>
+
+<VirtualHost *:80>
+ ServerName www.bar.com
+ DocumentRoot /apps/bar/public
+ PassengerHighPerformance on
+</VirtualHost>
+------------------------------------
+
+In the above example, high performance mode is only enabled for www.bar.com.
+It is disabled for everything else.
+
+If your application generally depends on mod_rewrite or other Apache modules,
+but a certain URL that's accessed often doesn't depend on those other modules,
+then you can enable high performance mode for a certain URL only. For example:
+
+------------------------------------
+<VirtualHost *:80>
+ ServerName www.foo.com
+ DocumentRoot /apps/foo/public
+ .... mod_rewrite rules or options for other Apache modules here ...
+
+ <Location /chatroom/ajax_update_poll>
+ PassengerHighPerformance on
+ </Location>
+</VirtualHost>
+------------------------------------
+
+This enables high performance mode for
+http://www.foo.com/chatroom/ajax_update_poll only.
+
+
+=== Compatibility options ===
+
+[[PassengerResolveSymlinksInDocumentRoot]]
+==== PassengerResolveSymlinksInDocumentRoot <on|off> ====
+Configures whether Phusion Passenger should resolve symlinks in the document root.
+Please refer to <<application_detection,How Phusion Passenger detects whether a
+virtual host is a web application>> for more information.
+
+This option may occur in the following places:
+
+ * In the global server configuration.
+ * In a virtual host configuration block.
+ * In a `<Directory>` or `<Location>` block.
+ * In '.htaccess', if `AllowOverride Options` is on.
+
+In each place, it may be specified at most once. It is off by default.
+
+==== PassengerAllowEncodedSlashes <on|off> ====
+By default, Apache doesn't support URLs with encoded slashes (%2f), e.g. URLs like
+this: `/users/fujikura%2fyuu`. If you access such an URL then Apache will return a
+404 Not Found error. This can be solved by turning on PassengerAllowEncodedSlashes
+as well as Apache's
+link:http://httpd.apache.org/docs/2.0/mod/core.html#allowencodedslashes[AllowEncodedSlashes].
+
+Is it important that you turn on both AllowEncodedSlashes *and* PassengerAllowEncodedSlashes,
+otherwise this feature will not work properly.
+
+PassengerAllowEncodedSlashes may occur in the following places:
+
+ * In the global server configuration.
+ * In a virtual host configuration block.
+ * In a `<Directory>` or `<Location>` block.
+ * In '.htaccess', if `AllowOverride Options` is on.
+
+In each place, it may be specified at most once. It is off by default.
+
+Please note however that turning on support for encoded slashes will break support for
+mod_rewrite passthrough rules. Because of bugs/limitations in Apache, Phusion Passenger
+can support either encoded slashes or mod_rewrite passthrough rules, but not both at the
+same time. Luckily this option can be specified anywhere, so you can enable it only for
+virtual hosts or URLs that need it:
+
+----------------------------------
+<VirtualHost *:80>
+ ServerName www.example.com
+ DocumentRoot /webapps/example/public
+ AllowEncodedSlashes on
+ RewriteEngine on
+
+ # Check for maintenance file and redirect all requests
+ RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
+ RewriteCond %{SCRIPT_FILENAME} !maintenance.html
+ RewriteRule ^.*$ /system/maintenance.html [L]
+
+ # Make /about an alias for /info/about.
+ RewriteRule ^/about$ /info/about [PT,L]
+
+ <Location ~ "^/users/">
+ # In a location block so that it doesn't interfere with the
+ # above /about mod_rewrite rule.
+ PassengerAllowEncodedSlashes on
+ </Location>
+</VirtualHost>
+----------------------------------
+
+With this, http://www.example.com/users/fujikura%2fyuu will work properly, and
+accessing http://www.example.com/about will properly display the result of
+http://www.example.com/info/about. Notice that PassengerAllowEncodedSlashes only
+interferes with passthrough rules, not with any other mod_rewrite rules. The rules for
+displaying maintenance.html will work fine even URLs starting with "/users".
+
=== Ruby on Rails-specific options ===
38 ext/apache2/Configuration.cpp
View
@@ -95,6 +95,7 @@ passenger_config_create_dir(apr_pool_t *p, char *dirspec) {
config->highPerformance = DirConfig::UNSET;
config->useGlobalQueue = DirConfig::UNSET;
config->resolveSymlinksInDocRoot = DirConfig::UNSET;
+ config->allowEncodedSlashes = DirConfig::UNSET;
config->statThrottleRate = 0;
config->statThrottleRateSpecified = false;
config->restartDir = NULL;
@@ -141,6 +142,7 @@ passenger_config_merge_dir(apr_pool_t *p, void *basev, void *addv) {
config->restartDir = (add->restartDir == NULL) ? base->restartDir : add->restartDir;
config->uploadBufferDir = (add->uploadBufferDir == NULL) ? base->uploadBufferDir : add->uploadBufferDir;
config->resolveSymlinksInDocRoot = (add->resolveSymlinksInDocRoot == DirConfig::UNSET) ? base->resolveSymlinksInDocRoot : add->resolveSymlinksInDocRoot;
+ config->allowEncodedSlashes = (add->allowEncodedSlashes == DirConfig::UNSET) ? base->allowEncodedSlashes : add->allowEncodedSlashes;
/*************************************/
return config;
}
@@ -429,6 +431,13 @@ cmd_passenger_resolve_symlinks_in_document_root(cmd_parms *cmd, void *pcfg, int
return NULL;
}
+static const char *
+cmd_passenger_allow_encoded_slashes(cmd_parms *cmd, void *pcfg, int arg) {
+ DirConfig *config = (DirConfig *) pcfg;
+ config->allowEncodedSlashes = (arg) ? DirConfig::ENABLED : DirConfig::DISABLED;
+ return NULL;
+}
+
/*************************************************
* Rails-specific settings
@@ -437,8 +446,16 @@ cmd_passenger_resolve_symlinks_in_document_root(cmd_parms *cmd, void *pcfg, int
static const char *
cmd_rails_base_uri(cmd_parms *cmd, void *pcfg, const char *arg) {
DirConfig *config = (DirConfig *) pcfg;
- config->railsBaseURIs.insert(arg);
- return NULL;
+ if (strlen(arg) == 0) {
+ return "RailsBaseURI may not be set to the empty string";
+ } else if (arg[0] != '/') {
+ return "RailsBaseURI must start with a slash (/)";
+ } else if (arg[strlen(arg) - 1] == '/') {
+ return "RailsBaseURI must not end with a slash (/)";
+ } else {
+ config->railsBaseURIs.insert(arg);
+ return NULL;
+ }
}
static const char *
@@ -519,8 +536,16 @@ cmd_rails_app_spawner_idle_time(cmd_parms *cmd, void *pcfg, const char *arg) {
static const char *
cmd_rack_base_uri(cmd_parms *cmd, void *pcfg, const char *arg) {
DirConfig *config = (DirConfig *) pcfg;
- config->rackBaseURIs.insert(arg);
- return NULL;
+ if (strlen(arg) == 0) {
+ return "RackBaseURI may not be set to the empty string";
+ } else if (arg[0] != '/') {
+ return "RackBaseURI must start with a slash (/)";
+ } else if (arg[strlen(arg) - 1] == '/') {
+ return "RackBaseURI must not end with a slash (/)";
+ } else {
+ config->rackBaseURIs.insert(arg);
+ return NULL;
+ }
}
static const char *
@@ -659,6 +684,11 @@ const command_rec passenger_commands[] = {
NULL,
OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
"Whether to resolve symlinks in the DocumentRoot path"),
+ AP_INIT_FLAG("PassengerAllowEncodedSlashes",
+ (FlagFunc) cmd_passenger_allow_encoded_slashes,
+ NULL,
+ OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
+ "Whether to support encoded slashes in the URL"),
/*****************************/
11 ext/apache2/Configuration.h
View
@@ -148,6 +148,13 @@
Threeway useGlobalQueue;
/**
+ * Whether encoded slashes in URLs should be supported. This however conflicts
+ * with mod_rewrite support because of a bug/limitation in Apache, so it's one
+ * or the other.
+ */
+ Threeway allowEncodedSlashes;
+
+ /**
* Throttle the number of stat() calls on files like
* restart.txt to the once per given number of seconds.
*/
@@ -253,6 +260,10 @@
return useGlobalQueue == ENABLED;
}
+ bool allowsEncodedSlashes() const {
+ return allowEncodedSlashes == ENABLED;
+ }
+
unsigned long getStatThrottleRate() const {
if (statThrottleRateSpecified) {
return statThrottleRate;
37 ext/apache2/Hooks.cpp
View
@@ -563,7 +563,7 @@ class Hooks {
}
UPDATE_TRACE_POINT();
- sendHeaders(r, session, mapper.getBaseURI());
+ sendHeaders(r, config, session, mapper.getBaseURI());
if (expectingUploadData) {
if (uploadDataFile != NULL) {
sendRequestBody(r, session, uploadDataFile);
@@ -784,13 +784,14 @@ class Hooks {
}
}
- apr_status_t sendHeaders(request_rec *r, Application::SessionPtr &session, const char *baseURI) {
+ apr_status_t sendHeaders(request_rec *r, DirConfig *config, Application::SessionPtr &session, const char *baseURI) {
apr_table_t *headers;
headers = apr_table_make(r->pool, 40);
if (headers == NULL) {
return APR_ENOMEM;
}
+
// Set standard CGI variables.
addHeader(headers, "SERVER_SOFTWARE", ap_get_server_version());
addHeader(headers, "SERVER_PROTOCOL", r->protocol);
@@ -802,17 +803,39 @@ class Hooks {
addHeader(headers, "REMOTE_PORT", apr_psprintf(r->pool, "%d", r->connection->remote_addr->port));
addHeader(headers, "REMOTE_USER", r->user);
addHeader(headers, "REQUEST_METHOD", r->method);
- addHeader(headers, "REQUEST_URI", r->unparsed_uri);
addHeader(headers, "QUERY_STRING", r->args ? r->args : "");
+ addHeader(headers, "HTTPS", lookupEnv(r, "HTTPS"));
+ addHeader(headers, "CONTENT_TYPE", lookupHeader(r, "Content-type"));
+ addHeader(headers, "DOCUMENT_ROOT", ap_document_root(r));
+
+ if (config->allowsEncodedSlashes()) {
+ /*
+ * Apache decodes encoded slashes in r->uri, so we must use r->unparsed_uri
+ * if we are to support encoded slashes. However mod_rewrite doesn't change
+ * r->unparsed_uri, so the user must make a choice between mod_rewrite
+ * support or encoded slashes support. Sucks. :-(
+ *
+ * http://code.google.com/p/phusion-passenger/issues/detail?id=113
+ * http://code.google.com/p/phusion-passenger/issues/detail?id=230
+ */
+ addHeader(headers, "REQUEST_URI", r->unparsed_uri);
+ } else {
+ const char *request_uri;
+ if (r->args != NULL) {
+ request_uri = apr_pstrcat(r->pool, r->uri, "?", r->args, NULL);
+ } else {
+ request_uri = r->uri;
+ }
+ addHeader(headers, "REQUEST_URI", request_uri);
+ }
+
if (strcmp(baseURI, "/") == 0) {
addHeader(headers, "SCRIPT_NAME", "");
+ addHeader(headers, "PATH_INFO", r->uri);
} else {
addHeader(headers, "SCRIPT_NAME", baseURI);
+ addHeader(headers, "PATH_INFO", r->uri + strlen(baseURI));
}
- addHeader(headers, "HTTPS", lookupEnv(r, "HTTPS"));
- addHeader(headers, "CONTENT_TYPE", lookupHeader(r, "Content-type"));
- addHeader(headers, "DOCUMENT_ROOT", ap_document_root(r));
- addHeader(headers, "PATH_INFO", r->parsed_uri.path);
// Set HTTP headers.
const apr_array_header_t *hdrs_arr;
18 ext/nginx/ContentHandler.c
View
@@ -288,14 +288,16 @@ create_request(ngx_http_request_t *r)
/* +1 for trailing null */
len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1;
- /* DOCUMENT_ROOT, SCRIPT_NAME and base URI */
+ /* DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT and PATH_INFO. */
len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1;
if (context->base_uri.len > 0) {
len += sizeof("SCRIPT_NAME") + context->base_uri.len + 1;
len += sizeof("RAILS_RELATIVE_URL_ROOT") +
context->base_uri.len + 1;
+ len += sizeof("PATH_INFO") + r->uri.len - context->base_uri.len + 1;
} else {
len += sizeof("SCRIPT_NAME") + sizeof("");
+ len += sizeof("PATH_INFO") + r->uri.len + 1;
}
/* Various other HTTP headers. */
@@ -445,7 +447,7 @@ create_request(ngx_http_request_t *r)
b->last = ngx_snprintf(b->last, 10, "%ui", content_length);
*b->last++ = (u_char) 0;
- /* Build DOCUMENT_ROOT, SCRIPT_NAME and base URI. */
+ /* Build DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT and PATH_INFO. */
b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT"));
b->last = ngx_copy(b->last, context->public_dir.data,
context->public_dir.len + 1);
@@ -459,9 +461,18 @@ create_request(ngx_http_request_t *r)
sizeof("RAILS_RELATIVE_URL_ROOT"));
b->last = ngx_copy(b->last, context->base_uri.data,
context->base_uri.len + 1);
+
+ b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
+ b->last = ngx_copy(b->last, r->uri.data + context->base_uri.len,
+ r->uri.len - context->base_uri.len);
+ b->last = ngx_copy(b->last, "", 1);
} else {
b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME"));
b->last = ngx_copy(b->last, "", sizeof(""));
+
+ b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO"));
+ b->last = ngx_copy(b->last, r->uri.data, r->uri.len);
+ b->last = ngx_copy(b->last, "", 1);
}
/* Various other HTTP headers. */
@@ -469,7 +480,8 @@ create_request(ngx_http_request_t *r)
&& r->headers_in.content_type->value.len > 0) {
b->last = ngx_copy(b->last, "CONTENT_TYPE", sizeof("CONTENT_TYPE"));
b->last = ngx_copy(b->last, r->headers_in.content_type->value.data,
- r->headers_in.content_type->value.len + 1);
+ r->headers_in.content_type->value.len);
+ b->last = ngx_copy(b->last, "", 1);
}
#if (NGX_HTTP_SSL)
7 lib/phusion_passenger/rack/request_handler.rb
View
@@ -42,10 +42,6 @@ class RequestHandler < AbstractRequestHandler
RACK_RUN_ONCE = "rack.run_once" # :nodoc:
RACK_URL_SCHEME = "rack.url_scheme" # :nodoc:
SCRIPT_NAME = "SCRIPT_NAME" # :nodoc:
- PATH_INFO = "PATH_INFO" # :nodoc:
- REQUEST_URI = "REQUEST_URI" # :nodoc:
- QUESTION_MARK = "?" # :nodoc:
- QUERY_STRING = "QUERY_STRING" # :nodoc:
CONTENT_LENGTH = "CONTENT_LENGTH" # :nodoc:
CONTENT_TYPE = "CONTENT_TYPE" # :nodoc:
HTTP_CONTENT_LENGTH = "HTTP_CONTENT_LENGTH" # :nodoc:
@@ -75,9 +71,6 @@ def process_request(env, input, output)
env[RACK_MULTITHREAD] = false
env[RACK_MULTIPROCESS] = true
env[RACK_RUN_ONCE] = false
- env[QUERY_STRING] ||= ""
- env[PATH_INFO] ||= env[REQUEST_URI].split(QUESTION_MARK, 2).first
- env[PATH_INFO].sub!(/^#{Regexp.escape(env[SCRIPT_NAME])}/, "")
if env[HTTP_CONTENT_LENGTH] && env[CONTENT_LENGTH]
env.delete(HTTP_CONTENT_LENGTH)
73 test/integration_tests/apache2_tests.rb
View
@@ -12,7 +12,7 @@
# TODO: test the 'RailsUserSwitching' and 'RailsDefaultUser' option.
# TODO: test custom page caching directory
-describe "mod_passenger running in Apache 2" do
+describe "Apache 2 module" do
include TestHelper
before :all do
@@ -33,6 +33,7 @@
describe ": MyCook(tm) beta running on root URI" do
before :all do
@web_server_supports_chunked_transfer_encoding = true
+ @base_uri = ""
@server = "http://passenger.test:#{@apache2.port}"
@apache2 << "RailsMaxPoolSize 1"
@stub = setup_rails_stub('mycook', 'tmp.mycook')
@@ -97,18 +98,12 @@
end
end
end
-
- it "supports environment variable passing through mod_env" do
- File.write("#{@stub.app_root}/public/.htaccess", 'SetEnv FOO "Foo Bar!"')
- File.touch("#{@stub.app_root}/tmp/restart.txt")
- get('/welcome/environment').should =~ /FOO = Foo Bar\!/
- get('/welcome/cgi_environment').should =~ /FOO = Foo Bar\!/
- end
end
describe ": MyCook(tm) beta running in a sub-URI" do
before :all do
@web_server_supports_chunked_transfer_encoding = true
+ @base_uri = "/mycook"
@stub = setup_rails_stub('mycook')
FileUtils.rm_rf('tmp.webdir')
FileUtils.mkdir_p('tmp.webdir')
@@ -128,6 +123,7 @@
before :each do
@server = "http://passenger.test:#{@apache2.port}/mycook"
+ @stub.reset
end
it_should_behave_like "MyCook(tm) beta"
@@ -138,13 +134,65 @@
end
end
+ describe "compatibility with other modules" do
+ before :all do
+ @apache2 << "RailsMaxPoolSize 1"
+
+ @mycook = setup_rails_stub('mycook', File.expand_path('tmp.mycook'))
+ @mycook_url_root = "http://1.passenger.test:#{@apache2.port}"
+ @apache2.set_vhost("1.passenger.test", "#{@mycook.app_root}/public") do |vhost|
+ vhost << "RewriteEngine on"
+ vhost << "RewriteRule ^/rewritten_welcome$ /welcome [PT,QSA,L]"
+ vhost << "RewriteRule ^/rewritten_cgi_environment$ /welcome/cgi_environment [PT,QSA,L]"
+ end
+ @apache2.start
+ end
+
+ after :all do
+ @mycook.destroy
+ end
+
+ before :each do
+ @mycook.reset
+ @server = @mycook_url_root
+ end
+
+ it "supports environment variable passing through mod_env" do
+ File.write("#{@mycook.app_root}/public/.htaccess", 'SetEnv FOO "Foo Bar!"')
+ File.touch("#{@mycook.app_root}/tmp/restart.txt") # Activate ENV changes.
+ get('/welcome/environment').should =~ /FOO = Foo Bar\!/
+ get('/welcome/cgi_environment').should =~ /FOO = Foo Bar\!/
+ end
+
+ it "supports mod_rewrite in the virtual host block" do
+ get('/rewritten_welcome').should =~ /Welcome to MyCook/
+ cgi_envs = get('/rewritten_cgi_environment?foo=bar+baz')
+ cgi_envs.should include("REQUEST_URI = /welcome/cgi_environment?foo=bar+baz\n")
+ cgi_envs.should include("PATH_INFO = /welcome/cgi_environment\n")
+ end
+
+ it "supports mod_rewrite in .htaccess" do
+ File.write("#{@mycook.app_root}/public/.htaccess", %Q{
+ RewriteEngine on
+ RewriteRule ^htaccess_welcome$ welcome [PT,QSA,L]
+ RewriteRule ^htaccess_cgi_environment$ welcome/cgi_environment [PT,QSA,L]
+ })
+ get('/htaccess_welcome').should =~ /Welcome to MyCook/
+ cgi_envs = get('/htaccess_cgi_environment?foo=bar+baz')
+ cgi_envs.should include("REQUEST_URI = /welcome/cgi_environment?foo=bar+baz\n")
+ cgi_envs.should include("PATH_INFO = /welcome/cgi_environment\n")
+ end
+ end
+
describe "configuration options" do
before :all do
@apache2 << "PassengerMaxPoolSize 3"
@mycook = setup_rails_stub('mycook', File.expand_path("tmp.mycook"))
@mycook_url_root = "http://1.passenger.test:#{@apache2.port}"
- @apache2.set_vhost('1.passenger.test', "#{@mycook.app_root}/public")
+ @apache2.set_vhost('1.passenger.test', "#{@mycook.app_root}/public") do |vhost|
+ vhost << "AllowEncodedSlashes on"
+ end
@apache2.set_vhost('2.passenger.test', "#{@mycook.app_root}/public") do |vhost|
vhost << "RailsAutoDetect off"
end
@@ -405,9 +453,16 @@ def index
get('/').should =~ /Welcome to MyCook/
ensure
FileUtils.rm_rf(orig_mycook_app_root)
+ @mycook.move(orig_mycook_app_root)
end
end
+ it "supports encoded slashes in the URL if AllowEncodedSlashes is turned on" do
+ @server = @mycook_url_root
+ File.write("#{@mycook.app_root}/public/.htaccess", "PassengerAllowEncodedSlashes on")
+ get('/welcome/show_id/foo%2fbar').should == 'foo/bar'
+ end
+
####################################
end
46 test/integration_tests/mycook_spec.rb
View
@@ -12,18 +12,15 @@
end
it "supports page caching on root/base URIs" do
- begin
- File.write("#{@stub.app_root}/public/index.html", "This is index.html.")
- get('/').should == "This is index.html."
- ensure
- File.unlink("#{@stub.app_root}/public/index.html") rescue nil
- end
+ File.write("#{@stub.app_root}/public/index.html", "This is index.html.")
+ get('/').should == "This is index.html."
end
it "doesn't use page caching if the HTTP request is not GET" do
post('/welcome/cached').should =~ %r{This content should never be displayed}
end
+ # TODO: move this to module compatibility tests
it "isn't interfered by Rails's default .htaccess dispatcher rules" do
get('/welcome/in_passenger').should == 'true'
end
@@ -95,19 +92,11 @@
end
end
- it "can properly handle custom headers" do
+ it "properly handles custom headers" do
response = get_response('/welcome/headers_test')
response["X-Foo"].should == "Bar"
end
-
- it "supports %2f in URIs" do
- get('/welcome/show_id/foo%2fbar').should == 'foo/bar'
- end
- specify "Rails's request.request_uri returns no an URI without hostname but with query_string" do
- get('/welcome/request_uri?foo=bar%20escaped').should =~ %r{/welcome/request_uri\?foo=bar%20escaped}
- end
-
it "supports restarting via restart.txt" do
controller = "#{@stub.app_root}/app/controllers/test_controller.rb"
restart_file = "#{@stub.app_root}/tmp/restart.txt"
@@ -161,6 +150,33 @@ def name
response["Status"].should == "404 Not Found"
end
+ describe "CGI environment variables compliance" do
+ specify "REQUEST_URI contains the request URI including query string" do
+ cgi_envs = get('/welcome/cgi_environment?foo=escaped%20string')
+ cgi_envs.should include("REQUEST_URI = #{@base_uri}/welcome/cgi_environment?foo=escaped%20string\n")
+ end
+
+ specify "PATH_INFO contains the request URI without the base URI and without the query string" do
+ cgi_envs = get('/welcome/cgi_environment?foo=escaped%20string')
+ cgi_envs.should include("PATH_INFO = /welcome/cgi_environment\n")
+ end
+
+ specify "QUERY_STRING contains the query string" do
+ cgi_envs = get('/welcome/cgi_environment?foo=escaped%20string')
+ cgi_envs.should include("QUERY_STRING = foo=escaped%20string\n")
+ end
+
+ specify "QUERY_STRING must be present even when there's no query string" do
+ cgi_envs = get('/welcome/cgi_environment')
+ cgi_envs.should include("QUERY_STRING = \n")
+ end
+
+ specify "SCRIPT_NAME contains the base URI, or the empty string if the app is deployed on the root URI" do
+ cgi_envs = get('/welcome/cgi_environment')
+ cgi_envs.should include("SCRIPT_NAME = #{@base_uri}\n")
+ end
+ end
+
if Process.uid == 0
it "runs as an unprivileged user" do
post('/welcome/touch')
17 test/integration_tests/nginx_tests.rb
View
@@ -38,10 +38,11 @@
describe "MyCook(tm) beta running a root URI" do
before :all do
- @server = "http://passenger.test:#{@nginx.port}"
+ @server = "http://1.passenger.test:#{@nginx.port}"
+ @base_uri = ""
@stub = setup_rails_stub('mycook')
@nginx.add_server do |server|
- server[:server_name] = "passenger.test"
+ server[:server_name] = "1.passenger.test"
server[:root] = File.expand_path("#{@stub.app_root}/public")
end
@nginx.start
@@ -51,11 +52,16 @@
@stub.destroy
end
+ before :each do
+ @stub.reset
+ end
+
it_should_behave_like "MyCook(tm) beta"
end
describe "MyCook(tm) beta running in a sub-URI" do
before :all do
+ @base_uri = "/mycook"
@stub = setup_rails_stub('mycook')
FileUtils.rm_rf('tmp.webdir')
FileUtils.mkdir_p('tmp.webdir')
@@ -63,7 +69,7 @@
FileUtils.ln_sf(File.expand_path(@stub.app_root) + "/public", 'tmp.webdir/mycook')
@nginx.add_server do |server|
- server[:server_name] = "passenger.test"
+ server[:server_name] = "1.passenger.test"
server[:root] = File.expand_path("tmp.webdir")
server[:passenger_base_uri] = "/mycook"
end
@@ -76,13 +82,14 @@
end
before :each do
- @server = "http://passenger.test:#{@nginx.port}/mycook"
+ @server = "http://1.passenger.test:#{@nginx.port}/mycook"
+ @stub.reset
end
it_should_behave_like "MyCook(tm) beta"
it "does not interfere with the root website" do
- @server = "http://passenger.test:#{@nginx.port}"
+ @server = "http://1.passenger.test:#{@nginx.port}"
get('/').should =~ /Zed, you rock\!/
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.