Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
...
  • 10 commits
  • 8 files changed
  • 0 commit comments
  • 4 contributors
View
28 NEWS
@@ -1,3 +1,31 @@
+Release 3.0.10
+--------------
+
+ * [Nginx] Dropped support for Nginx versions older than 1.0.0
+ * [Nginx] Fixed support for Nginx 1.1.8.
+ * [Nginx] New option passenger_max_requests
+ This is equivalent to the PassengerMaxRequests option in the Apache
+ version: Phusion Passenger will automatically shutdown a worker process
+ once it has processed the specified number of requests.
+ Contributed by Paul Kmiec.
+ * [Apache] New option PassengerBufferResponse
+ The Apache version did not buffer responses. This could block the Ruby
+ worker process in case of slow clients. We now enable response buffering
+ by default. It can be turned off through this option. Feature contributed
+ by Ryo Onodera.
+ * Fixed remaining Ruby 1.9.3 compatibility problems
+ We already supported Ruby 1.9.3 since 3.0.8, but due to bugs in Ruby
+ 1.9.3's build system Phusion Passenger would fail to detect Ruby 1.9.3
+ features on some systems. Fixes issue #714.
+ * Fixed a bug in PassengerPreStart
+ A regression was introduced in 3.0.8, causing the prespawn script to
+ connect to the host name instead of to 127.0.0.1. Fix contributed by
+ Andy Allan.
+ * Fixed various compilation problems.
+ * Fixed some Ruby 1.9 encoding problems.
+ * Fixed some Ruby 1.9.3 deprecation warnings.
+
+
Release 3.0.9
-------------
View
64 doc/Users guide Apache.txt
@@ -923,6 +923,70 @@ allow the attacker to cause a Denial-of-Service.
You can prevent this from happening by pointing PassengerRestartDir to a
directory that's readable by Apache, but only writable by administrators.
+[[PassengerBufferResponse]]
+=== PassengerBufferResponse <on|off> ===
+When turned on, application-generated responses are buffered in memory. By buffering
+responses, protection is provided against slow HTTP clients that can not read your
+response immediately.
+
+For example, consider an HTTP client that's on a dial-up modem link, and your
+application instance generates a 2 MB response. If response buffering is turned
+off then your application instance will be blocked until the entire 2 MB has been
+sent out to the HTTP client. This disallows your application instance to do any useful
+work in the mean time. By enabling response buffering, Phusion Passenger will read
+the application response as quickly as possible and will take care of slow clients.
+
+However, keep in mind that enabling this option will make streaming responses
+impossible. Consider for example this piece of Rails code:
+
+--------------------------------
+render :text => lambda { |response, output|
+ 10.times do |i|
+ output.write("entry #{i}\n")
+ output.flush
+ sleep 1
+ end
+}
+--------------------------------
+
+...or this piece of Rack code:
+
+--------------------------------
+class Response
+ def each
+ 10.times do |i|
+ yield("entry #{i}\n")
+ sleep 1
+ end
+ end
+end
+
+app = lambda do |env|
+ [200, { "Content-Type" => "text/plain" }, Response.new]
+end
+--------------------------------
+
+When response buffering is turned on, Phusion Passenger will wait until
+the application is done sending the entire response before forwarding it
+to the client. The client will not receive anything for 10 seconds,
+after which it receives the entire response at once.
+When response buffering is turned off, it works as expected: the client
+receives an "entry X" message every second for 10 seconds.
+
+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'.
+
+In each place, it may be specified at most once. The default value is 'on'.
+
+[NOTE]
+=====================================================
+The <<PassengerBufferResponse,PassengerBufferResponse>> directive should be turned off
+if responses can be huge. Because entire responses are buffered in memory when turned on.
+=====================================================
=== Security options ===
View
12 ext/apache2/Bucket.cpp
@@ -44,6 +44,7 @@ struct BucketData {
SessionPtr session;
PassengerBucketStatePtr state;
int stream;
+ bool bufferResponse;
~BucketData() {
/* The session here is an ApplicationPoolServer::RemoteSession.
@@ -80,7 +81,7 @@ bucket_read(apr_bucket *bucket, const char **str, apr_size_t *len, apr_read_type
*str = NULL;
*len = 0;
- if (block == APR_NONBLOCK_READ) {
+ if (!data->bufferResponse && block == APR_NONBLOCK_READ) {
/*
* The bucket brigade that Hooks::handleRequest() passes using
* ap_pass_brigade() is always passed through ap_content_length_filter,
@@ -130,7 +131,7 @@ bucket_read(apr_bucket *bucket, const char **str, apr_size_t *len, apr_read_type
* which can read the next chunk from the stream.
*/
APR_BUCKET_INSERT_AFTER(bucket, passenger_bucket_create(
- data->session, data->state, bucket->list));
+ data->session, data->state, bucket->list, data->bufferResponse));
/* The newly created Passenger Bucket has a reference to the session
* object, so we can delete data here.
@@ -163,11 +164,12 @@ bucket_read(apr_bucket *bucket, const char **str, apr_size_t *len, apr_read_type
}
static apr_bucket *
-passenger_bucket_make(apr_bucket *bucket, SessionPtr session, PassengerBucketStatePtr state) {
+passenger_bucket_make(apr_bucket *bucket, SessionPtr session, PassengerBucketStatePtr state, bool bufferResponse) {
BucketData *data = new BucketData();
data->session = session;
data->stream = session->getStream();
data->state = state;
+ data->bufferResponse = bufferResponse;
bucket->type = &apr_bucket_type_passenger_pipe;
bucket->length = (apr_size_t)(-1);
@@ -177,14 +179,14 @@ passenger_bucket_make(apr_bucket *bucket, SessionPtr session, PassengerBucketSta
}
apr_bucket *
-passenger_bucket_create(SessionPtr session, PassengerBucketStatePtr state, apr_bucket_alloc_t *list) {
+passenger_bucket_create(SessionPtr session, PassengerBucketStatePtr state, apr_bucket_alloc_t *list, bool bufferResponse) {
apr_bucket *bucket;
bucket = (apr_bucket *) apr_bucket_alloc(sizeof(*bucket), list);
APR_BUCKET_INIT(bucket);
bucket->free = apr_bucket_free;
bucket->list = list;
- return passenger_bucket_make(bucket, session, state);
+ return passenger_bucket_make(bucket, session, state, bufferResponse);
}
} // namespace Passenger
View
3 ext/apache2/Bucket.h
@@ -80,7 +80,8 @@ typedef shared_ptr<PassengerBucketState> PassengerBucketStatePtr;
*/
apr_bucket *passenger_bucket_create(SessionPtr session,
PassengerBucketStatePtr state,
- apr_bucket_alloc_t *list);
+ apr_bucket_alloc_t *list,
+ bool bufferResponse);
} // namespace Passenger
View
8 ext/apache2/Configuration.cpp
@@ -209,6 +209,7 @@ passenger_config_create_dir(apr_pool_t *p, char *dirspec) {
config->uploadBufferDir = NULL;
config->friendlyErrorPages = DirConfig::UNSET;
config->unionStationSupport = DirConfig::UNSET;
+ config->bufferResponse = DirConfig::UNSET;
/*************************************/
return config;
}
@@ -259,6 +260,7 @@ passenger_config_merge_dir(apr_pool_t *p, void *basev, void *addv) {
MERGE_THREEWAY_CONFIG(allowEncodedSlashes);
MERGE_THREEWAY_CONFIG(friendlyErrorPages);
MERGE_THREEWAY_CONFIG(unionStationSupport);
+ MERGE_THREEWAY_CONFIG(bufferResponse);
/*************************************/
return config;
}
@@ -313,6 +315,7 @@ DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_resolve_symlinks_in_document_roo
DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_allow_encoded_slashes, allowEncodedSlashes)
DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_friendly_error_pages, friendlyErrorPages)
DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_union_station_support, unionStationSupport)
+DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_buffer_response, bufferResponse)
static const char *
cmd_passenger_spawn_method(cmd_parms *cmd, void *pcfg, const char *arg) {
@@ -586,6 +589,11 @@ const command_rec passenger_commands[] = {
NULL,
OR_ALL,
"A filter for Union Station data."),
+ AP_INIT_FLAG("PassengerBufferResponse",
+ (FlagFunc) cmd_passenger_buffer_response,
+ NULL,
+ OR_ALL,
+ "Whether to enable buffering response."),
AP_INIT_FLAG("PassengerResolveSymlinksInDocumentRoot",
(FlagFunc) cmd_passenger_resolve_symlinks_in_document_root,
NULL,
View
9 ext/apache2/Configuration.hpp
@@ -192,6 +192,11 @@ struct DirConfig {
*/
Threeway unionStationSupport;
+ /**
+ * Whether response buffering support is enabled.
+ */
+ Threeway bufferResponse;
+
/*************************************/
/*************************************/
@@ -327,6 +332,10 @@ struct DirConfig {
bool useUnionStation() const {
return unionStationSupport == ENABLED;
}
+
+ bool getBufferResponse() const {
+ return bufferResponse != DISABLED;
+ }
string getUnionStationFilterString() const {
if (unionStationFilters.empty()) {
View
2 ext/apache2/Hooks.cpp
@@ -721,7 +721,7 @@ class Hooks {
/* Setup the bucket brigade. */
bucketState = ptr(new PassengerBucketState());
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
- b = passenger_bucket_create(session, bucketState, r->connection->bucket_alloc);
+ b = passenger_bucket_create(session, bucketState, r->connection->bucket_alloc, config->getBufferResponse());
/* The bucket (b) still has a reference to the session, so the reset()
* call here is guaranteed not to throw any exceptions.
View
2 helper-scripts/prespawn
@@ -102,7 +102,7 @@ class TCPPrespawnLocation < PrespawnLocation
end
def connect
- TCPSocket.new(request_host, request_port)
+ TCPSocket.new('127.0.0.1', request_port)
end
end

No commit comments for this range

Something went wrong with that request. Please try again.