passenger 4.0.25 → 4.0.26

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (38) hide show
  1. data.tar.gz.asc +7 -7
  2. data/NEWS +11 -0
  3. data/build/packaging.rb +3 -3
  4. data/debian.template/passenger.install.template +1 -1
  5. data/debian.template/rules.template +2 -1
  6. data/doc/Users guide Apache.idmap.txt +5 -3
  7. data/doc/Users guide Apache.txt +22 -0
  8. data/doc/Users guide Nginx.txt +12 -12
  9. data/doc/Users guide Standalone.txt +10 -1
  10. data/ext/apache2/ConfigurationCommands.cpp +18 -0
  11. data/ext/apache2/ConfigurationFields.hpp +6 -0
  12. data/ext/apache2/ConfigurationSetters.cpp +27 -0
  13. data/ext/apache2/CreateDirConfig.cpp +3 -0
  14. data/ext/apache2/DirectoryMapper.h +15 -6
  15. data/ext/apache2/Hooks.cpp +34 -10
  16. data/ext/apache2/MergeDirConfig.cpp +21 -0
  17. data/ext/apache2/SetHeaders.cpp +4 -0
  18. data/ext/common/Constants.h +1 -1
  19. data/ext/common/Utils.cpp +0 -1
  20. data/ext/common/Utils/VariantMap.h +1 -1
  21. data/ext/common/agents/HelperAgent/AgentOptions.h +4 -0
  22. data/ext/common/agents/HelperAgent/Main.cpp +10 -3
  23. data/ext/nginx/ContentHandler.c +2 -7
  24. data/helper-scripts/download_binaries/extconf.rb +7 -5
  25. data/lib/phusion_passenger.rb +1 -1
  26. data/lib/phusion_passenger/abstract_installer.rb +7 -22
  27. data/lib/phusion_passenger/admin_tools/memory_stats.rb +1 -1
  28. data/lib/phusion_passenger/apache2/config_options.rb +20 -0
  29. data/lib/phusion_passenger/standalone/runtime_installer.rb +69 -49
  30. data/lib/phusion_passenger/standalone/runtime_locator.rb +3 -3
  31. data/lib/phusion_passenger/standalone/start_command.rb +13 -1
  32. data/lib/phusion_passenger/utils/download.rb +193 -0
  33. data/resources/templates/standalone/config.erb +20 -3
  34. data/test/ruby/standalone/runtime_installer_spec.rb +69 -69
  35. data/test/ruby/standalone/runtime_locator_spec.rb +3 -3
  36. metadata +3 -3
  37. metadata.gz.asc +7 -7
  38. data/resources/templates/standalone/welcome.txt.erb +0 -8
data.tar.gz.asc CHANGED
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJSi8RJAAoJECrHRaUKISqMCSIIAI+VKk4qgW9zhjSUAZ7HsZbT
6
- jyB8LsJqSdcoenACclHob+RozCcvXFW2BLZp6tx6QrQV2HQ2nolNAFdVBO8SfgOf
7
- WC4AAeYby/GBCiRZHFN69zCxmp/WAgP/9GAsSAwJDhW/0qDjx36RWE+Z8Elq4wd/
8
- H31gpnOma9DD5rWSpFxYuqpT7MR6Ino4Bf1QnwpVo6tHpe2PO5wHA8fSiBwG+uyX
9
- VnCKWkpjqadczpdqHI//AftXo7LtLmDGFY/jA7LtISk4WPuH3PHAhXnblAxvFV4+
10
- bhZGqZionb1bq/OcWeB68Pa2IalxLLkZzi3NR08jnfjJuUuspQpvSQ5VQh78DCc=
11
- =aoKj
5
+ iQEcBAABAgAGBQJSlyZAAAoJECrHRaUKISqMPoYH/Re2+/VKPaDbGqAdn5Mkz+M6
6
+ GDSzfoGdSnaNN361EKI4kommvEaWYQOu3YoOMa5841rAc7e+cqlmLz4BM68qoNsx
7
+ 1Cc9QIBBuO0mwoxzze/Ecqfu/xDzSWC5LveDJb+GAWyk4YTUCUf8w82OTfqf/KSV
8
+ w0IlUApvPFW/Qpddq8g6VyYabcCcJdwa/UNVsCf4h+oTPMC8Ll3R3ZMX3Xzm0Fub
9
+ Au33s0RiVSaGkOhzPAGrDxbajt3pFBs/Gwc4aBJr6Kd5LEynETzZVkjxpDEUVVVd
10
+ lLjPk2hF3pKDy0ZCPPq75gzsgkgo0BZVM2s9auA1kFgIUqQnjkJS/c9FlfACaPo=
11
+ =FcDX
12
12
  -----END PGP SIGNATURE-----
data/NEWS CHANGED
@@ -1,3 +1,14 @@
1
+ Release 4.0.26
2
+ --------------
3
+
4
+ * Introduced the `PassengerBufferUpload` option for Apache. This option allows one
5
+ to disable upload buffering, e.g. in order to be able to track upload progress.
6
+ * [Nginx] The `HTTPS` variable is now set correctly for HTTPS connections, even
7
+ without setting `ssl on`. Fixes issue #401.
8
+ * [Standalone] It is now possible to listen on both a normal HTTP and an HTTPS port.
9
+ * [Enterprise] The `passenger-status` tool now displays rolling restart status.
10
+
11
+
1
12
  Release 4.0.25
2
13
  --------------
3
14
 
@@ -389,15 +389,15 @@ task :fakeroot => [:apache2, :nginx, :doc] do
389
389
  sh "mkdir -p #{fake_include_dir}"
390
390
  # Infer headers that the Nginx module needs
391
391
  headers = [
392
- ["ext/common/Exceptions.h", "Exceptions.h"]
392
+ ["ext/common/Exceptions.h", "common/Exceptions.h"]
393
393
  ]
394
394
  Dir["ext/nginx/*.[ch]"].each do |filename|
395
395
  File.read(filename).split("\n").grep(%r{#include "common/(.+)"}) do |match|
396
- headers << ["ext/common/#{$1}", $1]
396
+ headers << ["ext/common/#{$1}", "common/#{$1}"]
397
397
  end
398
398
  end
399
399
  headers.each do |header|
400
- target = "#{fake_include_dir}/common/#{header[1]}"
400
+ target = "#{fake_include_dir}/#{header[1]}"
401
401
  dir = File.dirname(target)
402
402
  if !File.directory?(dir)
403
403
  sh "mkdir -p #{dir}"
@@ -1,5 +1,5 @@
1
1
  usr/lib/<%= PhusionPassenger::GLOBAL_NAMESPACE_DIRNAME %>/agents/
2
- nginx-<%= PhusionPassenger::PREFERRED_NGINX_VERSION %>/objs/nginx usr/lib/<%= PhusionPassenger::GLOBAL_NAMESPACE_DIRNAME %>/
2
+ nginx-<%= PhusionPassenger::PREFERRED_NGINX_VERSION %>/objs/PassengerWebHelper usr/lib/<%= PhusionPassenger::GLOBAL_NAMESPACE_DIRNAME %>/
3
3
  usr/share/<%= PhusionPassenger::GLOBAL_NAMESPACE_DIRNAME %>/helper-scripts/
4
4
  usr/share/<%= PhusionPassenger::GLOBAL_NAMESPACE_DIRNAME %>/templates/
5
5
  usr/share/<%= PhusionPassenger::GLOBAL_NAMESPACE_DIRNAME %>/standalone_default_root/
@@ -31,7 +31,8 @@ override_dh_auto_build:
31
31
  ./configure --prefix=/tmp \
32
32
  <%= PhusionPassenger::STANDALONE_NGINX_CONFIGURE_OPTIONS %> \
33
33
  --add-module=`pwd`/../ext/nginx && \
34
- make
34
+ make && \
35
+ mv objs/nginx objs/PassengerWebHelper
35
36
 
36
37
  override_dh_auto_install:
37
38
  mkdir debian/tmp/
@@ -198,11 +198,13 @@
198
198
 
199
199
  6.7. Connection handling options => connection-handling-options-1k3zd1a
200
200
 
201
- 6.7.1. PassengerBufferResponse <on|off> => passengerbufferresponse-on-off--1y7ilka
201
+ 6.7.1. PassengerBufferUpload <on|off> => passengerbufferupload-on-off--1lsjr93
202
202
 
203
- 6.7.2. PassengerErrorOverride <on|off> => passengererroroverride-on-off--1pq9nez
203
+ 6.7.2. PassengerBufferResponse <on|off> => passengerbufferresponse-on-off--1y7ilka
204
204
 
205
- 6.7.3. PassengerMaxRequestQueueSize <number> => passenger-max-request-queue-size-number--1f1uocd
205
+ 6.7.3. PassengerErrorOverride <on|off> => passengererroroverride-on-off--1pq9nez
206
+
207
+ 6.7.4. PassengerMaxRequestQueueSize <number> => passenger-max-request-queue-size-number--1f1uocd
206
208
 
207
209
  6.8. Compatibility options => compatibility-options-8jve5a
208
210
 
@@ -1636,6 +1636,28 @@ http://www.foo.com/chatroom/ajax_update_poll only.
1636
1636
 
1637
1637
  === Connection handling options ===
1638
1638
 
1639
+ [[PassengerBufferUpload]]
1640
+ ==== PassengerBufferUpload <on|off> ====
1641
+ When turned on, HTTP request uploads (HTTP POST request bodies) will be buffered before sending the request to the application. Enabling upload buffering protects the application from slow clients, but will also prevent the ability to track upload progress.
1642
+
1643
+ If you want to allow your application to track upload progress, it is recommended that you disable upload buffering for specific URIs only. For example:
1644
+
1645
+ ------------------------
1646
+ # Disable upload buffering for /upload_video only.
1647
+ <Location /upload_video>
1648
+ PassengerBufferUpload off
1649
+ </Location>
1650
+ ------------------------
1651
+
1652
+ This option may occur in the following places:
1653
+
1654
+ * In the global server configuration.
1655
+ * In a virtual host configuration block.
1656
+ * In a `<Directory>` or `<Location>` block.
1657
+ * In '.htaccess'.
1658
+
1659
+ In each place, it may be specified at most once. The default value is 'on'.
1660
+
1639
1661
  [[PassengerBufferResponse]]
1640
1662
  ==== PassengerBufferResponse <on|off> ====
1641
1663
  When turned on, application-generated responses are buffered by Apache. Buffering will
@@ -89,9 +89,9 @@ And you want your Rails application, located in `/websites/rails`, to be accessi
89
89
 
90
90
  To do this, you need to perform the following:
91
91
 
92
- 1. Create a `location` with parameter `^/<SUBURI>(/|$)`. This is a regular expression that says: "match everything that is exactly <SUBURI>, or starts with <SUBDURI>/".
92
+ 1. Create a `location` with parameter `~ ^/<SUBURI>(/.*|$)`. This is a regular expression that says: "match everything that is exactly <SUBURI>, or starts with <SUBDURI>/".
93
93
  2. Inside the location block, set `passenger_base_uri <SUBURI>`.
94
- 3. Inside the location block, set `alias <PATH TO YOUR APPLICATION'S PUBLIC DIRECTORY>`.
94
+ 3. Inside the location block, set `alias <PATH TO YOUR APPLICATION'S PUBLIC DIRECTORY>$1`.
95
95
  4. Inside the location block, set `passenger_app_root <PATH TO YOUR APPLICATION ROOT>`.
96
96
  5. Inside the location block, re-specify `passenger_enabled on`.
97
97
 
@@ -107,9 +107,9 @@ http {
107
107
  root /websites/phusion;
108
108
 
109
109
  # This block has been added.
110
- location ^/subapp(/|$) {
110
+ location ~ ^/subapp(/.*|$) {
111
111
  passenger_base_uri /subapp;
112
- alias /websites/rails/public; # <-- be sure to point to 'public'!
112
+ alias /websites/rails/public$1; # <-- be sure to point to 'public'!
113
113
  passenger_app_root /websites/rails;
114
114
  passenger_enabled on;
115
115
  }
@@ -280,9 +280,9 @@ And you want your Rack application, located in `/websites/rack`, to be accessibl
280
280
 
281
281
  To do this, you need to perform the following:
282
282
 
283
- 1. Create a `location` with parameter `^/<SUBURI>(/|$)`. This is a regular expression that says: "match everything that is exactly <SUBURI>, or starts with <SUBDURI>/".
283
+ 1. Create a `location` with parameter `~ ^/<SUBURI>(/.*|$)`. This is a regular expression that says: "match everything that is exactly <SUBURI>, or starts with <SUBDURI>/".
284
284
  2. Inside the location block, set `passenger_base_uri <SUBURI>`.
285
- 3. Inside the location block, set `alias <PATH TO YOUR APPLICATION'S PUBLIC DIRECTORY>`.
285
+ 3. Inside the location block, set `alias <PATH TO YOUR APPLICATION'S PUBLIC DIRECTORY>$1`.
286
286
  4. Inside the location block, set `passenger_app_root <PATH TO YOUR APPLICATION ROOT>`.
287
287
  5. Inside the location block, re-specify `passenger_enabled on`.
288
288
 
@@ -298,9 +298,9 @@ http {
298
298
  root /websites/phusion;
299
299
 
300
300
  # This block has been added.
301
- location ^/subapp(/|$) {
301
+ location ~ ^/subapp(/.*|$) {
302
302
  passenger_base_uri /subapp;
303
- alias /websites/rack/public; # <-- be sure to point to 'public'!
303
+ alias /websites/rack/public$1; # <-- be sure to point to 'public'!
304
304
  passenger_app_root /websites/rack;
305
305
  passenger_enabled on;
306
306
  }
@@ -440,9 +440,9 @@ And you want your WSGI application, located in `/websites/wsgi`, to be accessibl
440
440
 
441
441
  To do this, you need to perform the following:
442
442
 
443
- 1. Create a `location` with parameter `^/<SUBURI>(/|$)`. This is a regular expression that says: "match everything that is exactly <SUBURI>, or starts with <SUBDURI>/".
443
+ 1. Create a `location` with parameter `~ ^/<SUBURI>(/.*|$)`. This is a regular expression that says: "match everything that is exactly <SUBURI>, or starts with <SUBDURI>/".
444
444
  2. Inside the location block, set `passenger_base_uri <SUBURI>`.
445
- 3. Inside the location block, set `alias <PATH TO YOUR APPLICATION'S PUBLIC DIRECTORY>`.
445
+ 3. Inside the location block, set `alias <PATH TO YOUR APPLICATION'S PUBLIC DIRECTORY>$1`.
446
446
  4. Inside the location block, set `passenger_app_root <PATH TO YOUR APPLICATION ROOT>`.
447
447
  5. Inside the location block, re-specify `passenger_enabled on`.
448
448
 
@@ -458,9 +458,9 @@ http {
458
458
  root /websites/phusion;
459
459
 
460
460
  # This block has been added.
461
- location ^/subapp(/|$) {
461
+ location ~ ^/subapp(/.*|$) {
462
462
  passenger_base_uri /subapp;
463
- alias /websites/wsgi/public; # <-- be sure to point to 'public'!
463
+ alias /websites/wsgi/public$1; # <-- be sure to point to 'public'!
464
464
  passenger_app_root /websites/wsgi;
465
465
  passenger_enabled on;
466
466
  }
@@ -36,7 +36,7 @@ passenger start
36
36
  Most configuration is done by customizing the arguments passed to the `passenger` command. The most important ones are:
37
37
 
38
38
  `--port NUMBER`::
39
- The port number that Phusion Passenger should listen on. Defaults to 3000.
39
+ The port number that Phusion Passenger Standalone should listen on. If not given, port 3000 is assumed.
40
40
  `--environment NAME`::
41
41
  Customizes the value of the `RAILS_ENV`, `RACK_ENV`, `WSGI_ENV`, `NODE_ENV` and `PASSENGER_ENV` environment variables. Some web frameworks, for example Rails and Connect.js, adjust their behavior according to the environment. The default value is 'development'.
42
42
  `--max-pool-size NUMBER`::
@@ -49,6 +49,13 @@ Most configuration is done by customizing the arguments passed to the `passenger
49
49
  If your app fails to start, Phusion Passenger will tell you by showing a friendly error page in the browser. This option disables it.
50
50
  `--ssl`::
51
51
  Enables SSL support. If this is set, you must also set `--ssl-certificate` and `--ssl-certificate-key` to the SSL certificate and key files, respectively.
52
+ `--ssl-port`::
53
+ If `--ssl` is given, and you set this option, then Phusion Passenger Standalone will listen for HTTP on the regular `--port` number, *as well as* listen for HTTPS on the port you specified with this option. For example:
54
+ +
55
+ ------------------------------------------------------------------------------
56
+ # Listen for HTTP on port 3000, HTTPS on port 3001.
57
+ passenger start --ssl --ssl-certificate ... --ssl-certificate-key ... --ssl-port 3001
58
+ ------------------------------------------------------------------------------
52
59
 
53
60
  See `--help` for all available options.
54
61
 
@@ -76,6 +83,8 @@ The following configuration options are supported:
76
83
  Equivalent to the `--spawn-method` command line option.
77
84
  `ssl`::
78
85
  Equivalent to the `--ssl` command line option. When given, you must also set `ssl_certificate` and `ssl_certificate_key` in the configuration file.
86
+ `ssl_port`::
87
+ Equivalent to the `--ssl-port` command line option.
79
88
  +
80
89
  When in mass deployment mode, you will probably want to set a different `port` too. If you don't, and you end up in a situation in which a port is used for both HTTP and HTTPS traffic, then the builtin Nginx core will abort with an error.
81
90
 
@@ -117,3 +117,21 @@
117
117
  OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
118
118
  "Whether to load environment variables from the shell before running the application."),
119
119
 
120
+ AP_INIT_FLAG("PassengerBufferUpload",
121
+ (FlagFunc) cmd_passenger_buffer_upload,
122
+ NULL,
123
+ OR_ALL,
124
+ "Whether to buffer file uploads."),
125
+
126
+ AP_INIT_TAKE1("PassengerAppType",
127
+ (Take1Func) cmd_passenger_app_type,
128
+ NULL,
129
+ OR_ALL,
130
+ "Force specific application type."),
131
+
132
+ AP_INIT_TAKE1("PassengerStartupFile",
133
+ (Take1Func) cmd_passenger_startup_file,
134
+ NULL,
135
+ OR_ALL,
136
+ "Force specific startup file."),
137
+
@@ -38,6 +38,8 @@
38
38
 
39
39
 
40
40
 
41
+ /** Whether to buffer file uploads. */
42
+ Threeway bufferUpload;
41
43
  /** Enable or disable Phusion Passenger. */
42
44
  Threeway enabled;
43
45
  /** Allow Apache to handle error response. */
@@ -54,6 +56,8 @@
54
56
  int minInstances;
55
57
  /** A timeout for application startup. */
56
58
  int startTimeout;
59
+ /** Force specific application type. */
60
+ const char *appType;
57
61
  /** The group that Ruby applications must run as. */
58
62
  const char *group;
59
63
  /** The Node.js command to use. */
@@ -62,6 +66,8 @@
62
66
  const char *python;
63
67
  /** The Ruby interpreter to use. */
64
68
  const char *ruby;
69
+ /** Force specific startup file. */
70
+ const char *startupFile;
65
71
  /** The user that Ruby applications must run as. */
66
72
  const char *user;
67
73
 
@@ -258,4 +258,31 @@
258
258
  return NULL;
259
259
  }
260
260
 
261
+
262
+ static const char *
263
+ cmd_passenger_buffer_upload(cmd_parms *cmd, void *pcfg, const char *arg) {
264
+ DirConfig *config = (DirConfig *) pcfg;
265
+ config->bufferUpload =
266
+ arg ?
267
+ DirConfig::ENABLED :
268
+ DirConfig::DISABLED;
269
+ return NULL;
270
+ }
271
+
272
+
273
+ static const char *
274
+ cmd_passenger_app_type(cmd_parms *cmd, void *pcfg, const char *arg) {
275
+ DirConfig *config = (DirConfig *) pcfg;
276
+ config->appType = arg;
277
+ return NULL;
278
+ }
279
+
280
+
281
+ static const char *
282
+ cmd_passenger_startup_file(cmd_parms *cmd, void *pcfg, const char *arg) {
283
+ DirConfig *config = (DirConfig *) pcfg;
284
+ config->startupFile = arg;
285
+ return NULL;
286
+ }
287
+
261
288
 
@@ -51,4 +51,7 @@
51
51
  config->enabled = DirConfig::UNSET;
52
52
  config->maxRequestQueueSize = UNSET_INT_VALUE;
53
53
  config->loadShellEnvvars = DirConfig::UNSET;
54
+ config->bufferUpload = DirConfig::UNSET;
55
+ config->appType = NULL;
56
+ config->startupFile = NULL;
54
57
 
@@ -145,13 +145,22 @@ private:
145
145
  AppTypeDetector detector(cstat, throttleRate);
146
146
  PassengerAppType appType;
147
147
  string appRoot;
148
- if (config->appRoot == NULL) {
149
- appType = detector.checkDocumentRoot(publicDir,
150
- baseURI != NULL || config->resolveSymlinksInDocRoot == DirConfig::ENABLED,
151
- &appRoot);
148
+ if (config->appType == NULL) {
149
+ if (config->appRoot == NULL) {
150
+ appType = detector.checkDocumentRoot(publicDir,
151
+ baseURI != NULL || config->resolveSymlinksInDocRoot == DirConfig::ENABLED,
152
+ &appRoot);
153
+ } else {
154
+ appRoot = config->appRoot;
155
+ appType = detector.checkAppRoot(appRoot);
156
+ }
152
157
  } else {
153
- appRoot = config->appRoot;
154
- appType = detector.checkAppRoot(appRoot);
158
+ if (config->appRoot == NULL) {
159
+ appType = PAT_NONE;
160
+ } else {
161
+ appRoot = config->appRoot;
162
+ appType = getAppType(config->appType);
163
+ }
155
164
  }
156
165
 
157
166
  this->appRoot = appRoot;
@@ -534,19 +534,21 @@ private:
534
534
  /********** Step 2: handle HTTP upload data, if any **********/
535
535
 
536
536
  int httpStatus = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK);
537
- if (httpStatus != OK) {
537
+ if (httpStatus != OK) {
538
538
  return httpStatus;
539
539
  }
540
540
 
541
541
  this_thread::disable_interruption di;
542
542
  this_thread::disable_syscall_interruption dsi;
543
543
  bool expectingUploadData;
544
+ bool shouldBufferUploads;
544
545
  string uploadDataMemory;
545
546
  boost::shared_ptr<BufferedUpload> uploadDataFile;
546
547
  const char *contentLength;
547
548
 
548
549
  expectingUploadData = ap_should_client_block(r);
549
550
  contentLength = lookupHeader(r, "Content-Length");
551
+ shouldBufferUploads = config->bufferUpload != DirConfig::DISABLED;
550
552
 
551
553
  /* If the HTTP upload data is larger than a threshold, or if the HTTP
552
554
  * client sent HTTP upload data using the "chunked" transfer encoding
@@ -557,17 +559,15 @@ private:
557
559
  * the HTTP client might block indefinitely until it's done uploading.
558
560
  * This would quickly exhaust the application pool.
559
561
  */
560
- if (expectingUploadData) {
562
+ if (expectingUploadData && shouldBufferUploads) {
561
563
  if (contentLength == NULL || atol(contentLength) > LARGE_UPLOAD_THRESHOLD) {
562
564
  uploadDataFile = receiveRequestBody(r);
563
565
  } else {
564
566
  receiveRequestBody(r, contentLength, uploadDataMemory);
565
567
  }
566
- }
567
-
568
- if (expectingUploadData) {
568
+
569
569
  /* We'll set the Content-Length header to the length of the
570
- * received upload data. Rails requires this header for its
570
+ * received upload data. Rails 2 requires this header for its
571
571
  * HTTP upload data multipart parsing process.
572
572
  * There are two reasons why we don't rely on the Content-Length
573
573
  * header as sent by the client:
@@ -606,16 +606,20 @@ private:
606
606
  sizeString[ret] = '\0';
607
607
  requestData[0] = StaticString(sizeString, ret);
608
608
 
609
- if (expectingUploadData && uploadDataFile == NULL) {
609
+ if (expectingUploadData && shouldBufferUploads && uploadDataFile == NULL) {
610
610
  requestData.push_back(uploadDataMemory);
611
611
  }
612
612
 
613
613
  FileDescriptor conn = connectToHelperAgent();
614
614
  gatheredWrite(conn, &requestData[0], requestData.size());
615
615
 
616
- if (expectingUploadData && uploadDataFile != NULL) {
617
- sendRequestBody(conn, uploadDataFile);
618
- uploadDataFile.reset();
616
+ if (expectingUploadData) {
617
+ if (shouldBufferUploads && uploadDataFile != NULL) {
618
+ sendRequestBody(conn, uploadDataFile);
619
+ uploadDataFile.reset();
620
+ } else if (!shouldBufferUploads) {
621
+ sendRequestBody(conn, r);
622
+ }
619
623
  }
620
624
 
621
625
  do {
@@ -1219,6 +1223,26 @@ private:
1219
1223
  }
1220
1224
  }
1221
1225
 
1226
+ void sendRequestBody(const FileDescriptor &fd, request_rec *r) {
1227
+ TRACE_POINT();
1228
+ char buf[1024 * 32];
1229
+ apr_off_t len;
1230
+
1231
+ try {
1232
+ while ((len = readRequestBodyFromApache(r, buf, sizeof(buf))) > 0) {
1233
+ writeExact(fd, buf, len);
1234
+ }
1235
+ } catch (const SystemException &e) {
1236
+ if (e.code() == EPIPE || e.code() == ECONNRESET) {
1237
+ // The HelperAgent stopped reading the body, probably
1238
+ // because the application already sent EOF.
1239
+ return;
1240
+ } else {
1241
+ throw e;
1242
+ }
1243
+ }
1244
+ }
1245
+
1222
1246
  public:
1223
1247
  Hooks(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
1224
1248
  : cstat(1024),
@@ -130,3 +130,24 @@
130
130
  add->loadShellEnvvars;
131
131
 
132
132
 
133
+
134
+ config->bufferUpload =
135
+ (add->bufferUpload == DirConfig::UNSET) ?
136
+ base->bufferUpload :
137
+ add->bufferUpload;
138
+
139
+
140
+
141
+ config->appType =
142
+ (add->appType == NULL) ?
143
+ base->appType :
144
+ add->appType;
145
+
146
+
147
+
148
+ config->startupFile =
149
+ (add->startupFile == NULL) ?
150
+ base->startupFile :
151
+ add->startupFile;
152
+
153
+