<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -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, &quot;PassengerAllowEncodedSlashes&quot;, 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</diff>
      <filename>NEWS</filename>
    </modified>
    <modified>
      <diff>@@ -678,21 +678,6 @@ Example:
 &lt;/VirtualHost&gt;
 -----------------------------
 
-[[PassengerResolveSymlinksInDocumentRoot]]
-=== PassengerResolveSymlinksInDocumentRoot &lt;on|off&gt; ===
-Configures whether Phusion Passenger should resolve symlinks in the document root.
-Please refer to &lt;&lt;application_detection,How Phusion Passenger detects whether a
-virtual host is a web application&gt;&gt; for more information.
-
-This option may occur in the following places:
-
- * In the global server configuration.
- * In a virtual host configuration block.
- * In a `&lt;Directory&gt;` or `&lt;Location&gt;` 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 &lt;on|off&gt; ===
 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 &lt;on|off&gt; ===
-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 `&lt;Directory&gt;` or `&lt;Location&gt;` 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:
-
-------------------------------------
-&lt;VirtualHost *:80&gt;
-    ServerName www.foo.com
-    DocumentRoot /apps/foo/public
-    .... mod_rewrite rules or options for other Apache modules here ...
-&lt;/VirtualHost&gt;
-
-&lt;VirtualHost *:80&gt;
-    ServerName www.bar.com
-    DocumentRoot /apps/bar/public
-    PassengerHighPerformance on
-&lt;/VirtualHost&gt;
-------------------------------------
-
-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:
-
-------------------------------------
-&lt;VirtualHost *:80&gt;
-    ServerName www.foo.com
-    DocumentRoot /apps/foo/public
-    .... mod_rewrite rules or options for other Apache modules here ...
-    
-    &lt;Location /chatroom/ajax_update_poll&gt;
-        PassengerHighPerformance on
-    &lt;/Location&gt;
-&lt;/VirtualHost&gt;
-------------------------------------
-
-This enables high performance mode for
-http://www.foo.com/chatroom/ajax_update_poll only.
-
 === PassengerEnabled &lt;on|off&gt; ===
 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 &lt;on|off&gt; ====
+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 `&lt;Directory&gt;` or `&lt;Location&gt;` 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:
+
+------------------------------------
+&lt;VirtualHost *:80&gt;
+    ServerName www.foo.com
+    DocumentRoot /apps/foo/public
+    .... mod_rewrite rules or options for other Apache modules here ...
+&lt;/VirtualHost&gt;
+
+&lt;VirtualHost *:80&gt;
+    ServerName www.bar.com
+    DocumentRoot /apps/bar/public
+    PassengerHighPerformance on
+&lt;/VirtualHost&gt;
+------------------------------------
+
+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:
+
+------------------------------------
+&lt;VirtualHost *:80&gt;
+    ServerName www.foo.com
+    DocumentRoot /apps/foo/public
+    .... mod_rewrite rules or options for other Apache modules here ...
+    
+    &lt;Location /chatroom/ajax_update_poll&gt;
+        PassengerHighPerformance on
+    &lt;/Location&gt;
+&lt;/VirtualHost&gt;
+------------------------------------
+
+This enables high performance mode for
+http://www.foo.com/chatroom/ajax_update_poll only.
+
+
+=== Compatibility options ===
+
+[[PassengerResolveSymlinksInDocumentRoot]]
+==== PassengerResolveSymlinksInDocumentRoot &lt;on|off&gt; ====
+Configures whether Phusion Passenger should resolve symlinks in the document root.
+Please refer to &lt;&lt;application_detection,How Phusion Passenger detects whether a
+virtual host is a web application&gt;&gt; for more information.
+
+This option may occur in the following places:
+
+ * In the global server configuration.
+ * In a virtual host configuration block.
+ * In a `&lt;Directory&gt;` or `&lt;Location&gt;` block.
+ * In '.htaccess', if `AllowOverride Options` is on.
+
+In each place, it may be specified at most once. It is off by default.
+
+==== PassengerAllowEncodedSlashes &lt;on|off&gt; ====
+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 `&lt;Directory&gt;` or `&lt;Location&gt;` 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:
+
+----------------------------------
+&lt;VirtualHost *:80&gt;
+    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]
+    
+    &lt;Location ~ &quot;^/users/&quot;&gt;
+        # In a location block so that it doesn't interfere with the
+        # above /about mod_rewrite rule.
+        PassengerAllowEncodedSlashes on
+    &lt;/Location&gt;
+&lt;/VirtualHost&gt;
+----------------------------------
+
+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 &quot;/users&quot;.
+
 
 === Ruby on Rails-specific options ===
 </diff>
      <filename>doc/Users guide Apache.txt</filename>
    </modified>
    <modified>
      <diff>@@ -95,6 +95,7 @@ passenger_config_create_dir(apr_pool_t *p, char *dirspec) {
 	config-&gt;highPerformance = DirConfig::UNSET;
 	config-&gt;useGlobalQueue = DirConfig::UNSET;
 	config-&gt;resolveSymlinksInDocRoot = DirConfig::UNSET;
+	config-&gt;allowEncodedSlashes = DirConfig::UNSET;
 	config-&gt;statThrottleRate = 0;
 	config-&gt;statThrottleRateSpecified = false;
 	config-&gt;restartDir = NULL;
@@ -141,6 +142,7 @@ passenger_config_merge_dir(apr_pool_t *p, void *basev, void *addv) {
 	config-&gt;restartDir = (add-&gt;restartDir == NULL) ? base-&gt;restartDir : add-&gt;restartDir;
 	config-&gt;uploadBufferDir = (add-&gt;uploadBufferDir == NULL) ? base-&gt;uploadBufferDir : add-&gt;uploadBufferDir;
 	config-&gt;resolveSymlinksInDocRoot = (add-&gt;resolveSymlinksInDocRoot == DirConfig::UNSET) ? base-&gt;resolveSymlinksInDocRoot : add-&gt;resolveSymlinksInDocRoot;
+	config-&gt;allowEncodedSlashes = (add-&gt;allowEncodedSlashes == DirConfig::UNSET) ? base-&gt;allowEncodedSlashes : add-&gt;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-&gt;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-&gt;railsBaseURIs.insert(arg);
-	return NULL;
+	if (strlen(arg) == 0) {
+		return &quot;RailsBaseURI may not be set to the empty string&quot;;
+	} else if (arg[0] != '/') {
+		return &quot;RailsBaseURI must start with a slash (/)&quot;;
+	} else if (arg[strlen(arg) - 1] == '/') {
+		return &quot;RailsBaseURI must not end with a slash (/)&quot;;
+	} else {
+		config-&gt;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-&gt;rackBaseURIs.insert(arg);
-	return NULL;
+	if (strlen(arg) == 0) {
+		return &quot;RackBaseURI may not be set to the empty string&quot;;
+	} else if (arg[0] != '/') {
+		return &quot;RackBaseURI must start with a slash (/)&quot;;
+	} else if (arg[strlen(arg) - 1] == '/') {
+		return &quot;RackBaseURI must not end with a slash (/)&quot;;
+	} else {
+		config-&gt;rackBaseURIs.insert(arg);
+		return NULL;
+	}
 }
 
 static const char *
@@ -659,6 +684,11 @@ const command_rec passenger_commands[] = {
 		NULL,
 		OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
 		&quot;Whether to resolve symlinks in the DocumentRoot path&quot;),
+	AP_INIT_FLAG(&quot;PassengerAllowEncodedSlashes&quot;,
+		(FlagFunc) cmd_passenger_allow_encoded_slashes,
+		NULL,
+		OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
+		&quot;Whether to support encoded slashes in the URL&quot;),
 	
 	/*****************************/
 </diff>
      <filename>ext/apache2/Configuration.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -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;</diff>
      <filename>ext/apache2/Configuration.h</filename>
    </modified>
    <modified>
      <diff>@@ -563,7 +563,7 @@ private:
 			}
 			
 			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 @@ private:
 		}
 	}
 	
-	apr_status_t sendHeaders(request_rec *r, Application::SessionPtr &amp;session, const char *baseURI) {
+	apr_status_t sendHeaders(request_rec *r, DirConfig *config, Application::SessionPtr &amp;session, const char *baseURI) {
 		apr_table_t *headers;
 		headers = apr_table_make(r-&gt;pool, 40);
 		if (headers == NULL) {
 			return APR_ENOMEM;
 		}
 		
+		
 		// Set standard CGI variables.
 		addHeader(headers, &quot;SERVER_SOFTWARE&quot;, ap_get_server_version());
 		addHeader(headers, &quot;SERVER_PROTOCOL&quot;, r-&gt;protocol);
@@ -802,17 +803,39 @@ private:
 		addHeader(headers, &quot;REMOTE_PORT&quot;,     apr_psprintf(r-&gt;pool, &quot;%d&quot;, r-&gt;connection-&gt;remote_addr-&gt;port));
 		addHeader(headers, &quot;REMOTE_USER&quot;,     r-&gt;user);
 		addHeader(headers, &quot;REQUEST_METHOD&quot;,  r-&gt;method);
-		addHeader(headers, &quot;REQUEST_URI&quot;,     r-&gt;unparsed_uri);
 		addHeader(headers, &quot;QUERY_STRING&quot;,    r-&gt;args ? r-&gt;args : &quot;&quot;);
+		addHeader(headers, &quot;HTTPS&quot;,           lookupEnv(r, &quot;HTTPS&quot;));
+		addHeader(headers, &quot;CONTENT_TYPE&quot;,    lookupHeader(r, &quot;Content-type&quot;));
+		addHeader(headers, &quot;DOCUMENT_ROOT&quot;,   ap_document_root(r));
+		
+		if (config-&gt;allowsEncodedSlashes()) {
+			/*
+			 * Apache decodes encoded slashes in r-&gt;uri, so we must use r-&gt;unparsed_uri
+			 * if we are to support encoded slashes. However mod_rewrite doesn't change
+			 * r-&gt;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, &quot;REQUEST_URI&quot;, r-&gt;unparsed_uri);
+		} else {
+			const char *request_uri;
+			if (r-&gt;args != NULL) {
+				request_uri = apr_pstrcat(r-&gt;pool, r-&gt;uri, &quot;?&quot;, r-&gt;args, NULL);
+			} else {
+				request_uri = r-&gt;uri;
+			}
+			addHeader(headers, &quot;REQUEST_URI&quot;, request_uri);
+		}
+		
 		if (strcmp(baseURI, &quot;/&quot;) == 0) {
 			addHeader(headers, &quot;SCRIPT_NAME&quot;, &quot;&quot;);
+			addHeader(headers, &quot;PATH_INFO&quot;, r-&gt;uri);
 		} else {
 			addHeader(headers, &quot;SCRIPT_NAME&quot;, baseURI);
+			addHeader(headers, &quot;PATH_INFO&quot;, r-&gt;uri + strlen(baseURI));
 		}
-		addHeader(headers, &quot;HTTPS&quot;,           lookupEnv(r, &quot;HTTPS&quot;));
-		addHeader(headers, &quot;CONTENT_TYPE&quot;,    lookupHeader(r, &quot;Content-type&quot;));
-		addHeader(headers, &quot;DOCUMENT_ROOT&quot;,   ap_document_root(r));
-		addHeader(headers, &quot;PATH_INFO&quot;,       r-&gt;parsed_uri.path);
 		
 		// Set HTTP headers.
 		const apr_array_header_t *hdrs_arr;</diff>
      <filename>ext/apache2/Hooks.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -288,14 +288,16 @@ create_request(ngx_http_request_t *r)
     /* +1 for trailing null */
     len = sizeof(&quot;CONTENT_LENGTH&quot;) + ngx_strlen(buf) + 1;
     
-    /* DOCUMENT_ROOT, SCRIPT_NAME and base URI */
+    /* DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT and PATH_INFO. */
     len += sizeof(&quot;DOCUMENT_ROOT&quot;) + context-&gt;public_dir.len + 1;
     if (context-&gt;base_uri.len &gt; 0) {
         len += sizeof(&quot;SCRIPT_NAME&quot;) + context-&gt;base_uri.len + 1;
         len += sizeof(&quot;RAILS_RELATIVE_URL_ROOT&quot;) +
                context-&gt;base_uri.len + 1;
+        len += sizeof(&quot;PATH_INFO&quot;) + r-&gt;uri.len - context-&gt;base_uri.len + 1;
     } else {
         len += sizeof(&quot;SCRIPT_NAME&quot;) + sizeof(&quot;&quot;);
+        len += sizeof(&quot;PATH_INFO&quot;) + r-&gt;uri.len + 1;
     }
     
     /* Various other HTTP headers. */
@@ -445,7 +447,7 @@ create_request(ngx_http_request_t *r)
     b-&gt;last = ngx_snprintf(b-&gt;last, 10, &quot;%ui&quot;, content_length);
     *b-&gt;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-&gt;last = ngx_copy(b-&gt;last, &quot;DOCUMENT_ROOT&quot;, sizeof(&quot;DOCUMENT_ROOT&quot;));
     b-&gt;last = ngx_copy(b-&gt;last, context-&gt;public_dir.data,
                        context-&gt;public_dir.len + 1);
@@ -459,9 +461,18 @@ create_request(ngx_http_request_t *r)
                            sizeof(&quot;RAILS_RELATIVE_URL_ROOT&quot;));
         b-&gt;last = ngx_copy(b-&gt;last, context-&gt;base_uri.data,
                            context-&gt;base_uri.len + 1);
+        
+        b-&gt;last = ngx_copy(b-&gt;last, &quot;PATH_INFO&quot;, sizeof(&quot;PATH_INFO&quot;));
+        b-&gt;last = ngx_copy(b-&gt;last, r-&gt;uri.data + context-&gt;base_uri.len,
+                           r-&gt;uri.len - context-&gt;base_uri.len);
+        b-&gt;last = ngx_copy(b-&gt;last, &quot;&quot;, 1);
     } else {
         b-&gt;last = ngx_copy(b-&gt;last, &quot;SCRIPT_NAME&quot;, sizeof(&quot;SCRIPT_NAME&quot;));
         b-&gt;last = ngx_copy(b-&gt;last, &quot;&quot;, sizeof(&quot;&quot;));
+        
+        b-&gt;last = ngx_copy(b-&gt;last, &quot;PATH_INFO&quot;, sizeof(&quot;PATH_INFO&quot;));
+        b-&gt;last = ngx_copy(b-&gt;last, r-&gt;uri.data, r-&gt;uri.len);
+        b-&gt;last = ngx_copy(b-&gt;last, &quot;&quot;, 1);
     }
     
     /* Various other HTTP headers. */
@@ -469,7 +480,8 @@ create_request(ngx_http_request_t *r)
      &amp;&amp; r-&gt;headers_in.content_type-&gt;value.len &gt; 0) {
         b-&gt;last = ngx_copy(b-&gt;last, &quot;CONTENT_TYPE&quot;, sizeof(&quot;CONTENT_TYPE&quot;));
         b-&gt;last = ngx_copy(b-&gt;last, r-&gt;headers_in.content_type-&gt;value.data,
-                           r-&gt;headers_in.content_type-&gt;value.len + 1);
+                           r-&gt;headers_in.content_type-&gt;value.len);
+        b-&gt;last = ngx_copy(b-&gt;last, &quot;&quot;, 1);
     }
     
     #if (NGX_HTTP_SSL)</diff>
      <filename>ext/nginx/ContentHandler.c</filename>
    </modified>
    <modified>
      <diff>@@ -42,10 +42,6 @@ class RequestHandler &lt; AbstractRequestHandler
 	RACK_RUN_ONCE      = &quot;rack.run_once&quot;       # :nodoc:
 	RACK_URL_SCHEME	   = &quot;rack.url_scheme&quot;     # :nodoc:
 	SCRIPT_NAME        = &quot;SCRIPT_NAME&quot;         # :nodoc:
-	PATH_INFO          = &quot;PATH_INFO&quot;           # :nodoc:
-	REQUEST_URI        = &quot;REQUEST_URI&quot;         # :nodoc:
-	QUESTION_MARK      = &quot;?&quot;                   # :nodoc:
-	QUERY_STRING       = &quot;QUERY_STRING&quot;        # :nodoc:
 	CONTENT_LENGTH      = &quot;CONTENT_LENGTH&quot;       # :nodoc:
 	CONTENT_TYPE        = &quot;CONTENT_TYPE&quot;         # :nodoc:
 	HTTP_CONTENT_LENGTH = &quot;HTTP_CONTENT_LENGTH&quot;  # :nodoc:
@@ -75,9 +71,6 @@ protected
 			env[RACK_MULTITHREAD]  = false
 			env[RACK_MULTIPROCESS] = true
 			env[RACK_RUN_ONCE]     = false
-			env[QUERY_STRING]    ||= &quot;&quot;
-			env[PATH_INFO]       ||= env[REQUEST_URI].split(QUESTION_MARK, 2).first
-			env[PATH_INFO].sub!(/^#{Regexp.escape(env[SCRIPT_NAME])}/, &quot;&quot;)
 			
 			if env[HTTP_CONTENT_LENGTH] &amp;&amp; env[CONTENT_LENGTH]
 				env.delete(HTTP_CONTENT_LENGTH)</diff>
      <filename>lib/phusion_passenger/rack/request_handler.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,7 +12,7 @@ require 'integration_tests/hello_world_wsgi_spec'
 # TODO: test the 'RailsUserSwitching' and 'RailsDefaultUser' option.
 # TODO: test custom page caching directory
 
-describe &quot;mod_passenger running in Apache 2&quot; do
+describe &quot;Apache 2 module&quot; do
 	include TestHelper
 	
 	before :all do
@@ -33,6 +33,7 @@ describe &quot;mod_passenger running in Apache 2&quot; do
 	describe &quot;: MyCook(tm) beta running on root URI&quot; do
 		before :all do
 			@web_server_supports_chunked_transfer_encoding = true
+			@base_uri = &quot;&quot;
 			@server = &quot;http://passenger.test:#{@apache2.port}&quot;
 			@apache2 &lt;&lt; &quot;RailsMaxPoolSize 1&quot;
 			@stub = setup_rails_stub('mycook', 'tmp.mycook')
@@ -97,18 +98,12 @@ describe &quot;mod_passenger running in Apache 2&quot; do
 				end
 			end
 		end
-		
-		it &quot;supports environment variable passing through mod_env&quot; do
-			File.write(&quot;#{@stub.app_root}/public/.htaccess&quot;, 'SetEnv FOO &quot;Foo Bar!&quot;')
-			File.touch(&quot;#{@stub.app_root}/tmp/restart.txt&quot;)
-			get('/welcome/environment').should =~ /FOO = Foo Bar\!/
-			get('/welcome/cgi_environment').should =~ /FOO = Foo Bar\!/
-		end
 	end
 	
 	describe &quot;: MyCook(tm) beta running in a sub-URI&quot; do
 		before :all do
 			@web_server_supports_chunked_transfer_encoding = true
+			@base_uri = &quot;/mycook&quot;
 			@stub = setup_rails_stub('mycook')
 			FileUtils.rm_rf('tmp.webdir')
 			FileUtils.mkdir_p('tmp.webdir')
@@ -128,6 +123,7 @@ describe &quot;mod_passenger running in Apache 2&quot; do
 		
 		before :each do
 			@server = &quot;http://passenger.test:#{@apache2.port}/mycook&quot;
+			@stub.reset
 		end
 		
 		it_should_behave_like &quot;MyCook(tm) beta&quot;
@@ -138,13 +134,65 @@ describe &quot;mod_passenger running in Apache 2&quot; do
 		end
 	end
 	
+	describe &quot;compatibility with other modules&quot; do
+		before :all do
+			@apache2 &lt;&lt; &quot;RailsMaxPoolSize 1&quot;
+			
+			@mycook = setup_rails_stub('mycook', File.expand_path('tmp.mycook'))
+			@mycook_url_root = &quot;http://1.passenger.test:#{@apache2.port}&quot;
+			@apache2.set_vhost(&quot;1.passenger.test&quot;, &quot;#{@mycook.app_root}/public&quot;) do |vhost|
+				vhost &lt;&lt; &quot;RewriteEngine on&quot;
+				vhost &lt;&lt; &quot;RewriteRule ^/rewritten_welcome$ /welcome [PT,QSA,L]&quot;
+				vhost &lt;&lt; &quot;RewriteRule ^/rewritten_cgi_environment$ /welcome/cgi_environment [PT,QSA,L]&quot;
+			end
+			@apache2.start
+		end
+		
+		after :all do
+			@mycook.destroy
+		end
+		
+		before :each do
+			@mycook.reset
+			@server = @mycook_url_root
+		end
+		
+		it &quot;supports environment variable passing through mod_env&quot; do
+			File.write(&quot;#{@mycook.app_root}/public/.htaccess&quot;, 'SetEnv FOO &quot;Foo Bar!&quot;')
+			File.touch(&quot;#{@mycook.app_root}/tmp/restart.txt&quot;)  # Activate ENV changes.
+			get('/welcome/environment').should =~ /FOO = Foo Bar\!/
+			get('/welcome/cgi_environment').should =~ /FOO = Foo Bar\!/
+		end
+		
+		it &quot;supports mod_rewrite in the virtual host block&quot; do
+			get('/rewritten_welcome').should =~ /Welcome to MyCook/
+			cgi_envs = get('/rewritten_cgi_environment?foo=bar+baz')
+			cgi_envs.should include(&quot;REQUEST_URI = /welcome/cgi_environment?foo=bar+baz\n&quot;)
+			cgi_envs.should include(&quot;PATH_INFO = /welcome/cgi_environment\n&quot;)
+		end
+		
+		it &quot;supports mod_rewrite in .htaccess&quot; do
+			File.write(&quot;#{@mycook.app_root}/public/.htaccess&quot;, %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(&quot;REQUEST_URI = /welcome/cgi_environment?foo=bar+baz\n&quot;)
+			cgi_envs.should include(&quot;PATH_INFO = /welcome/cgi_environment\n&quot;)
+		end
+	end
+	
 	describe &quot;configuration options&quot; do
 		before :all do
 			@apache2 &lt;&lt; &quot;PassengerMaxPoolSize 3&quot;
 			
 			@mycook = setup_rails_stub('mycook', File.expand_path(&quot;tmp.mycook&quot;))
 			@mycook_url_root = &quot;http://1.passenger.test:#{@apache2.port}&quot;
-			@apache2.set_vhost('1.passenger.test', &quot;#{@mycook.app_root}/public&quot;)
+			@apache2.set_vhost('1.passenger.test', &quot;#{@mycook.app_root}/public&quot;) do |vhost|
+				vhost &lt;&lt; &quot;AllowEncodedSlashes on&quot;
+			end
 			@apache2.set_vhost('2.passenger.test', &quot;#{@mycook.app_root}/public&quot;) do |vhost|
 				vhost &lt;&lt; &quot;RailsAutoDetect off&quot;
 			end
@@ -405,9 +453,16 @@ describe &quot;mod_passenger running in Apache 2&quot; do
 				get('/').should =~ /Welcome to MyCook/
 			ensure
 				FileUtils.rm_rf(orig_mycook_app_root)
+				@mycook.move(orig_mycook_app_root)
 			end
 		end
 		
+		it &quot;supports encoded slashes in the URL if AllowEncodedSlashes is turned on&quot; do
+			@server = @mycook_url_root
+			File.write(&quot;#{@mycook.app_root}/public/.htaccess&quot;, &quot;PassengerAllowEncodedSlashes on&quot;)
+			get('/welcome/show_id/foo%2fbar').should == 'foo/bar'
+		end
+		
 		####################################
 	end
 	</diff>
      <filename>test/integration_tests/apache2_tests.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,18 +12,15 @@ shared_examples_for &quot;MyCook(tm) beta&quot; do
 	end
 	
 	it &quot;supports page caching on root/base URIs&quot; do
-		begin
-			File.write(&quot;#{@stub.app_root}/public/index.html&quot;, &quot;This is index.html.&quot;)
-			get('/').should == &quot;This is index.html.&quot;
-		ensure
-			File.unlink(&quot;#{@stub.app_root}/public/index.html&quot;) rescue nil
-		end
+		File.write(&quot;#{@stub.app_root}/public/index.html&quot;, &quot;This is index.html.&quot;)
+		get('/').should == &quot;This is index.html.&quot;
 	end
 	
 	it &quot;doesn't use page caching if the HTTP request is not GET&quot; do
 		post('/welcome/cached').should =~ %r{This content should never be displayed}
 	end
 	
+	# TODO: move this to module compatibility tests
 	it &quot;isn't interfered by Rails's default .htaccess dispatcher rules&quot; do
 		get('/welcome/in_passenger').should == 'true'
 	end
@@ -95,19 +92,11 @@ shared_examples_for &quot;MyCook(tm) beta&quot; do
 		end
 	end
 	
-	it &quot;can properly handle custom headers&quot; do
+	it &quot;properly handles custom headers&quot; do
 		response = get_response('/welcome/headers_test')
 		response[&quot;X-Foo&quot;].should == &quot;Bar&quot;
 	end
-
-	it &quot;supports %2f in URIs&quot; do
-		get('/welcome/show_id/foo%2fbar').should == 'foo/bar'
-	end
 	
-	specify &quot;Rails's request.request_uri returns no an URI without hostname but with query_string&quot; do
-		get('/welcome/request_uri?foo=bar%20escaped').should =~ %r{/welcome/request_uri\?foo=bar%20escaped}
-	end
-
 	it &quot;supports restarting via restart.txt&quot; do
 		controller = &quot;#{@stub.app_root}/app/controllers/test_controller.rb&quot;
 		restart_file = &quot;#{@stub.app_root}/tmp/restart.txt&quot;
@@ -161,6 +150,33 @@ shared_examples_for &quot;MyCook(tm) beta&quot; do
 		response[&quot;Status&quot;].should == &quot;404 Not Found&quot;
 	end
 	
+	describe &quot;CGI environment variables compliance&quot; do
+		specify &quot;REQUEST_URI contains the request URI including query string&quot; do
+			cgi_envs = get('/welcome/cgi_environment?foo=escaped%20string')
+			cgi_envs.should include(&quot;REQUEST_URI = #{@base_uri}/welcome/cgi_environment?foo=escaped%20string\n&quot;)
+		end
+		
+		specify &quot;PATH_INFO contains the request URI without the base URI and without the query string&quot; do
+			cgi_envs = get('/welcome/cgi_environment?foo=escaped%20string')
+			cgi_envs.should include(&quot;PATH_INFO = /welcome/cgi_environment\n&quot;)
+		end
+		
+		specify &quot;QUERY_STRING contains the query string&quot; do
+			cgi_envs = get('/welcome/cgi_environment?foo=escaped%20string')
+			cgi_envs.should include(&quot;QUERY_STRING = foo=escaped%20string\n&quot;)
+		end
+		
+		specify &quot;QUERY_STRING must be present even when there's no query string&quot; do
+			cgi_envs = get('/welcome/cgi_environment')
+			cgi_envs.should include(&quot;QUERY_STRING = \n&quot;)
+		end
+		
+		specify &quot;SCRIPT_NAME contains the base URI, or the empty string if the app is deployed on the root URI&quot; do
+			cgi_envs = get('/welcome/cgi_environment')
+			cgi_envs.should include(&quot;SCRIPT_NAME = #{@base_uri}\n&quot;)
+		end
+	end
+	
 	if Process.uid == 0
 		it &quot;runs as an unprivileged user&quot; do
 			post('/welcome/touch')</diff>
      <filename>test/integration_tests/mycook_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -38,10 +38,11 @@ describe &quot;Phusion Passenger for Nginx&quot; do
 	
 	describe &quot;MyCook(tm) beta running a root URI&quot; do
 		before :all do
-			@server = &quot;http://passenger.test:#{@nginx.port}&quot;
+			@server = &quot;http://1.passenger.test:#{@nginx.port}&quot;
+			@base_uri = &quot;&quot;
 			@stub = setup_rails_stub('mycook')
 			@nginx.add_server do |server|
-				server[:server_name] = &quot;passenger.test&quot;
+				server[:server_name] = &quot;1.passenger.test&quot;
 				server[:root]        = File.expand_path(&quot;#{@stub.app_root}/public&quot;)
 			end
 			@nginx.start
@@ -51,11 +52,16 @@ describe &quot;Phusion Passenger for Nginx&quot; do
 			@stub.destroy
 		end
 		
+		before :each do
+			@stub.reset
+		end
+		
 		it_should_behave_like &quot;MyCook(tm) beta&quot;
 	end
 	
 	describe &quot;MyCook(tm) beta running in a sub-URI&quot; do
 		before :all do
+			@base_uri = &quot;/mycook&quot;
 			@stub = setup_rails_stub('mycook')
 			FileUtils.rm_rf('tmp.webdir')
 			FileUtils.mkdir_p('tmp.webdir')
@@ -63,7 +69,7 @@ describe &quot;Phusion Passenger for Nginx&quot; do
 			FileUtils.ln_sf(File.expand_path(@stub.app_root) + &quot;/public&quot;, 'tmp.webdir/mycook')
 			
 			@nginx.add_server do |server|
-				server[:server_name] = &quot;passenger.test&quot;
+				server[:server_name] = &quot;1.passenger.test&quot;
 				server[:root]        = File.expand_path(&quot;tmp.webdir&quot;)
 				server[:passenger_base_uri] = &quot;/mycook&quot;
 			end
@@ -76,13 +82,14 @@ describe &quot;Phusion Passenger for Nginx&quot; do
 		end
 		
 		before :each do
-			@server = &quot;http://passenger.test:#{@nginx.port}/mycook&quot;
+			@server = &quot;http://1.passenger.test:#{@nginx.port}/mycook&quot;
+			@stub.reset
 		end
 		
 		it_should_behave_like &quot;MyCook(tm) beta&quot;
 		
 		it &quot;does not interfere with the root website&quot; do
-			@server = &quot;http://passenger.test:#{@nginx.port}&quot;
+			@server = &quot;http://1.passenger.test:#{@nginx.port}&quot;
 			get('/').should =~ /Zed, you rock\!/
 		end
 	end</diff>
      <filename>test/integration_tests/nginx_tests.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>7ec85d760645a4340f8fb33341ea56e12444ea6d</id>
    </parent>
  </parents>
  <author>
    <name>Hongli Lai (Phusion)</name>
    <email>hongli@phusion.nl</email>
  </author>
  <url>http://github.com/FooBarWidget/passenger/commit/caa9fd7626761b2f3421012a6a9ed86f9b200d9d</url>
  <id>caa9fd7626761b2f3421012a6a9ed86f9b200d9d</id>
  <committed-date>2009-08-26T05:30:26-07:00</committed-date>
  <authored-date>2009-08-26T05:29:24-07:00</authored-date>
  <message>Fix support for mod_rewrite passthrough rules (issue #230) and fix some WSGI compliance issues (issue #360).</message>
  <tree>446514fee862e0073c26a11a4ff100941fd92b5f</tree>
  <committer>
    <name>Hongli Lai (Phusion)</name>
    <email>hongli@phusion.nl</email>
  </committer>
</commit>
