passenger 5.0.0.beta1 → 5.0.0.beta2
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.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/CHANGELOG +33 -0
- data/CONTRIBUTORS +2 -0
- data/build/agents.rb +3 -0
- data/build/packaging.rb +1 -1
- data/doc/Packaging.txt.md +1 -1
- data/doc/users_guide_snippets/tips.txt +1 -1
- data/ext/apache2/Hooks.cpp +3 -12
- data/ext/common/ApplicationPool2/Implementation.cpp +1 -1
- data/ext/common/ApplicationPool2/Options.h +3 -0
- data/ext/common/ApplicationPool2/Process.h +9 -11
- data/ext/common/ApplicationPool2/Spawner.h +6 -2
- data/ext/common/Constants.h +1 -1
- data/ext/common/ServerKit/HeaderTable.h +28 -4
- data/ext/common/ServerKit/Implementation.cpp +5 -1
- data/ext/common/agents/HelperAgent/Main.cpp +17 -0
- data/ext/common/agents/HelperAgent/OptionParser.h +15 -0
- data/ext/common/agents/HelperAgent/RequestHandler.h +6 -0
- data/ext/common/agents/HelperAgent/RequestHandler/AppResponse.h +1 -0
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +36 -0
- data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +1 -0
- data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +5 -4
- data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +28 -2
- data/ext/common/agents/HelperAgent/ResponseCache.h +1 -1
- data/ext/ruby/extconf.rb +2 -0
- data/ext/ruby/passenger_native_support.c +40 -13
- data/lib/phusion_passenger.rb +1 -1
- data/lib/phusion_passenger/config/admin_command_command.rb +2 -2
- data/lib/phusion_passenger/config/main.rb +1 -1
- data/lib/phusion_passenger/config/system_metrics_command.rb +7 -2
- data/lib/phusion_passenger/platform_info/operating_system.rb +6 -6
- data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +11 -1
- data/node_lib/phusion_passenger/line_reader.js +3 -1
- data/test/cxx/ServerKit/HeaderTableTest.cpp +7 -1
- metadata +2 -2
- metadata.gz.asc +7 -7
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
Yzc0NjVmNTJlYTZmYWExZjBmZTEyZDFjODliMDg2YTBiZWI5ZmQ2MA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
YzJmMGQxZmU1NmY5ODcxNTBiZWZlZThmMjhiYTE1NjVmNThiYjkxNw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZmY1NmQwMzNkZmFhYWQ1MWVjMDFkYWQwYzRlNDdhNzI1MjI3MjUwODUyOGI5
|
10
|
+
ZjFkMmRkOTY0NzE2YTUyYmI4YzEwNjJiOTIwZWNmNzMwMTc2YzM0NWEzMzY4
|
11
|
+
NGVhMjQ4MjA4MWRmMjkzMmMwOGE2MjdmNzVmY2M1ZWU2NmIxMTE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTA0ZGVkNjg2NWM1YzRkZTBmMjAwMDM0MmYyNjJjNTNiMmNiZWEzNTIyNTQw
|
14
|
+
ZDM0NzljODkwNWVlMjU5NDIxOWRkODMwNmJkNDc4MTE1ZmZmNjAxZTE3NmFj
|
15
|
+
YzE3ODgyOTM4N2EzYjg5NDJlNGRhMWQ3NjFmZTg2YWJjZmNlYTY=
|
checksums.yaml.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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJUlA2PAAoJECrHRaUKISqMfFcH/RERmONzrpkI9JVi+JxjUFRf
|
6
|
+
u9QT0kBu8VDYhaZEHQHvhVsTKKu+6+9qa0td1B9CFf2M+pdEakCIqIWCxb0dQVme
|
7
|
+
/F4z+pprnCEUwc348iynv0evSQ7dUhQphNGL0cCXDGDuMrGxbQxP7DRiyc2h99un
|
8
|
+
CVWuQGwZvnMGnJ4gmQjTKLalnMVHxEkEwukuhPFbuMEt6lzo4JXzTc3/STRSkt1J
|
9
|
+
ZnXeFOR8ifkynyvNv7wgbIv1r4iAWSn0L2c1P2ou1MnghQhjBDs2XJDnZ1KjDuML
|
10
|
+
f1AoWn/VyWi4HkyqAvVhFxCCr0WoyWmQ2uhD5vikwPHVrxoKbQGP2OJwk+FbltI=
|
11
|
+
=CGbg
|
12
12
|
-----END PGP SIGNATURE-----
|
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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJUlA2PAAoJECrHRaUKISqMKGAH/At3Qmxna8prw6C4gGN2quRk
|
6
|
+
B29MiVrX/mt82dUhM4+ENRSN4Anxzj+ZiIzjts/ko4LO5z7imX6/Yg9yVu+JX2+K
|
7
|
+
DPmmmvvAfFhwslVf3bbL5f9bmaS1AV9Vh0a0TJtN2kv+wKmOJ0olbA8mYmC3TQh+
|
8
|
+
Ypg23/0FgGNESTM19RL5cr4govT8xd2/qYAn+WauXqmxaXLfRZFLXpDOrVQJztIu
|
9
|
+
AZA7FfhEaFRUv+2YB2iiO474AUIdCNpksWIs/q3bKJHy+buMsytFCWD5UcBt5Cfu
|
10
|
+
rli1TCrwxgnHTes5rrXWvAeQyJzmwQmhA6A8co6F6xOArfZmxZRfegD8Z82fY/M=
|
11
|
+
=MeVu
|
12
12
|
-----END PGP SIGNATURE-----
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
Release 5.0.0 beta 2
|
2
|
+
--------------------
|
3
|
+
|
4
|
+
* Fixed handling of multiple Set-Cookie headers. Closes GH-1296.
|
5
|
+
* `passenger-config system-metrics` now works properly if the agent is installed in ~/.passenger. Closes GH-1304.
|
6
|
+
* Documentation enhancements by Igor Vuk. Closes GH-1318.
|
7
|
+
* Fixed some crasher bugs.
|
8
|
+
* [Standalone] User switching is now correctly disabled.
|
9
|
+
* [Standalone] Fixed the `--thread-count` parameter.
|
10
|
+
* [Apache] IPs set by mod_remoteip are now respected. Closes GH-1284.
|
11
|
+
* [Apache] Fixed support for gzipped chunked responses. Closes GH-1309.
|
12
|
+
|
13
|
+
|
1
14
|
Release 5.0.0 beta 1
|
2
15
|
--------------------
|
3
16
|
|
@@ -31,6 +44,26 @@ Minor changes:
|
|
31
44
|
* [Standalone] `passenger-standalone.json`/`Passengerfile.json` no longer overrides command line options. Instead, command line options now have the highest priority.
|
32
45
|
|
33
46
|
|
47
|
+
Release 4.0.56
|
48
|
+
--------------
|
49
|
+
|
50
|
+
* Fixed a file descriptor leak that manifests when an error page is shown. Contributed by Paul Bonaud, closes GH-1325.
|
51
|
+
* Improved Node.js request load balancing. Closes GH-1322. Thanks to Charles Vallières for the analysis.
|
52
|
+
|
53
|
+
|
54
|
+
Release 4.0.55
|
55
|
+
--------------
|
56
|
+
|
57
|
+
* Supports Ruby 2.2. Closes GH-1314.
|
58
|
+
* Fixed Linux OS name detection.
|
59
|
+
|
60
|
+
|
61
|
+
Release 4.0.54
|
62
|
+
--------------
|
63
|
+
|
64
|
+
* Contains a licensing-related hot fix for Enterprise customers.
|
65
|
+
|
66
|
+
|
34
67
|
Release 4.0.53
|
35
68
|
--------------
|
36
69
|
|
data/CONTRIBUTORS
CHANGED
@@ -30,6 +30,7 @@ Gokulnath Manakkattil
|
|
30
30
|
Gregory Potamianos
|
31
31
|
Hongli Lai (Phusion)
|
32
32
|
Ian Ehlert
|
33
|
+
Igor Vuk
|
33
34
|
isaac
|
34
35
|
Isaac Reuben
|
35
36
|
J Smith
|
@@ -57,6 +58,7 @@ Nathaniel Bibler
|
|
57
58
|
Neil Wilson
|
58
59
|
Ninh Bui (Phusion)
|
59
60
|
Pat Downey
|
61
|
+
Paul B
|
60
62
|
Paul Kmiec
|
61
63
|
Pepijn Looije
|
62
64
|
Perry Smith
|
data/build/agents.rb
CHANGED
@@ -62,6 +62,9 @@ AGENT_OBJECTS = {
|
|
62
62
|
'ext/common/ServerKit/HttpHeaderParser.h',
|
63
63
|
'ext/common/ServerKit/AcceptLoadBalancer.h',
|
64
64
|
'ext/common/ServerKit/FileBufferedChannel.h',
|
65
|
+
'ext/common/ApplicationPool2/Pool.h',
|
66
|
+
'ext/common/ApplicationPool2/Group.h',
|
67
|
+
'ext/common/ApplicationPool2/Spawner.h',
|
65
68
|
'ext/common/Constants.h',
|
66
69
|
'ext/common/StaticString.h',
|
67
70
|
'ext/common/Account.h',
|
data/build/packaging.rb
CHANGED
@@ -142,7 +142,7 @@ task 'package:release' => ['package:set_official', 'package:gem', 'package:tarba
|
|
142
142
|
end
|
143
143
|
|
144
144
|
if is_open_source?
|
145
|
-
if boolean_option('HOMEBREW_UPDATE', true)
|
145
|
+
if boolean_option('HOMEBREW_UPDATE', true) && !is_beta
|
146
146
|
puts "Updating Homebrew formula..."
|
147
147
|
Rake::Task['package:update_homebrew'].invoke
|
148
148
|
else
|
data/doc/Packaging.txt.md
CHANGED
@@ -233,7 +233,7 @@ a list of all possible assets and asset directories.
|
|
233
233
|
|
234
234
|
The directory that contains the source code for the Phusion Passenger Ruby
|
235
235
|
extension. Phusion Passenger uses these sources to build a Ruby extension,
|
236
|
-
when it detects that the user is using a new Ruby
|
236
|
+
when it detects that the user is using a new Ruby interpreter for which
|
237
237
|
no Ruby extension has been compiled.
|
238
238
|
|
239
239
|
Value when originally packaged: `<SOURCE_ROOT>/ext/ruby`.
|
@@ -799,7 +799,7 @@ server {
|
|
799
799
|
--------------------
|
800
800
|
endif::nginx[]
|
801
801
|
|
802
|
-
Then you need to install a Ruby 1.9-compatible Ruby
|
802
|
+
Then you need to install a Ruby 1.9-compatible Ruby interpreter with POSIX spawn support, alongside JRuby/MRI 1.8. Ruby interpreters which can be used for running the Flying Passenger daemon include:
|
803
803
|
|
804
804
|
* MRI Ruby >= 1.9.
|
805
805
|
* Rubinius.
|
data/ext/apache2/Hooks.cpp
CHANGED
@@ -706,16 +706,6 @@ private:
|
|
706
706
|
return 0;
|
707
707
|
}
|
708
708
|
|
709
|
-
/**
|
710
|
-
* Checks case-insensitively whether the given header is "Transfer-Encoding".
|
711
|
-
*/
|
712
|
-
bool headerIsTransferEncoding(const char *headerName, size_t len) const {
|
713
|
-
return len == sizeof("transfer-encoding") - 1 &&
|
714
|
-
apr_tolower(headerName[0]) == (u_char) 't' &&
|
715
|
-
apr_tolower(headerName[sizeof("transfer-encoding") - 2]) == (u_char) 'g' &&
|
716
|
-
apr_strnatcasecmp(headerName + 1, "ransfer-encoding") == 0;
|
717
|
-
}
|
718
|
-
|
719
709
|
/**
|
720
710
|
* Convert an HTTP header name to a CGI environment name.
|
721
711
|
*/
|
@@ -892,7 +882,7 @@ private:
|
|
892
882
|
|
893
883
|
#if HTTP_VERSION(AP_SERVER_MAJORVERSION_NUMBER, AP_SERVER_MINORVERSION_NUMBER) >= 2004
|
894
884
|
addHeader(result, P_STATIC_STRING("!~REMOTE_ADDR"),
|
895
|
-
r->
|
885
|
+
r->useragent_ip);
|
896
886
|
addHeader(r, result, P_STATIC_STRING("!~REMOTE_PORT"),
|
897
887
|
r->connection->client_addr->port);
|
898
888
|
#else
|
@@ -979,10 +969,11 @@ private:
|
|
979
969
|
|
980
970
|
// Add flags.
|
981
971
|
// C = Strip 100 Continue header
|
972
|
+
// D = Dechunk
|
982
973
|
// B = Buffer request body
|
983
974
|
// S = SSL
|
984
975
|
|
985
|
-
result.append("!~FLAGS:
|
976
|
+
result.append("!~FLAGS: CD", sizeof("!~FLAGS: CD") - 1);
|
986
977
|
if (config->bufferUpload != DirConfig::DISABLED) {
|
987
978
|
result.append("B", 1);
|
988
979
|
}
|
@@ -184,7 +184,6 @@ void processAndLogNewSpawnException(SpawnException &e, const Options &options,
|
|
184
184
|
|
185
185
|
try {
|
186
186
|
int fd = -1;
|
187
|
-
FdGuard guard(fd, true);
|
188
187
|
string errorPage;
|
189
188
|
|
190
189
|
UPDATE_TRACE_POINT();
|
@@ -199,6 +198,7 @@ void processAndLogNewSpawnException(SpawnException &e, const Options &options,
|
|
199
198
|
getSystemTempDir());
|
200
199
|
fd = mkstemp(filename);
|
201
200
|
#endif
|
201
|
+
FdGuard guard(fd, true);
|
202
202
|
if (fd == -1) {
|
203
203
|
int e = errno;
|
204
204
|
throw SystemException("Cannot generate a temporary filename",
|
@@ -283,6 +283,8 @@ public:
|
|
283
283
|
*/
|
284
284
|
bool loadShellEnvvars;
|
285
285
|
|
286
|
+
bool userSwitching;
|
287
|
+
|
286
288
|
/** Whether Union Station logging should be enabled. Enabling this option will
|
287
289
|
* result in:
|
288
290
|
*
|
@@ -455,6 +457,7 @@ public:
|
|
455
457
|
rights(DEFAULT_BACKEND_ACCOUNT_RIGHTS),
|
456
458
|
debugger(false),
|
457
459
|
loadShellEnvvars(true),
|
460
|
+
userSwitching(true),
|
458
461
|
analytics(false),
|
459
462
|
raiseInternalError(false),
|
460
463
|
|
@@ -534,19 +534,17 @@ public:
|
|
534
534
|
int busyness() const {
|
535
535
|
/* Different processes within a Group may have different
|
536
536
|
* 'concurrency' values. We want:
|
537
|
-
* -
|
538
|
-
* - to give processes with concurrency == 0 more priority
|
539
|
-
* with concurrency > 0.
|
540
|
-
* Therefore,
|
541
|
-
*
|
537
|
+
* - the process with the smallest busyness to be be picked for routing.
|
538
|
+
* - to give processes with concurrency == 0 more priority (in general)
|
539
|
+
* over processes with concurrency > 0.
|
540
|
+
* Therefore, in case of processes with concurrency > 0, we describe our
|
541
|
+
* busyness as a percentage of 'concurrency', with the percentage value
|
542
|
+
* in [0..INT_MAX] instead of [0..1]. That way, the busyness value
|
543
|
+
* of processes with concurrency > 0 is usually higher than that of processes
|
544
|
+
* with concurrency == 0.
|
542
545
|
*/
|
543
546
|
if (concurrency == 0) {
|
544
|
-
|
545
|
-
if (sessions == 0) {
|
546
|
-
return 0;
|
547
|
-
} else {
|
548
|
-
return 1;
|
549
|
-
}
|
547
|
+
return sessions;
|
550
548
|
} else {
|
551
549
|
return (int) (((long long) sessions * INT_MAX) / (double) concurrency);
|
552
550
|
}
|
@@ -924,7 +924,9 @@ protected:
|
|
924
924
|
|
925
925
|
UPDATE_TRACE_POINT();
|
926
926
|
userInfo = (struct passwd *) NULL;
|
927
|
-
if (!options.
|
927
|
+
if (!options.userSwitching) {
|
928
|
+
// Keep userInfo at NULL so that it's set to defaultUser's UID.
|
929
|
+
} else if (!options.user.empty()) {
|
928
930
|
ret = getpwnam_r(options.user.c_str(), &pwd, pwdBuf.get(),
|
929
931
|
pwdBufSize, &userInfo);
|
930
932
|
if (ret != 0) {
|
@@ -953,7 +955,9 @@ protected:
|
|
953
955
|
}
|
954
956
|
|
955
957
|
UPDATE_TRACE_POINT();
|
956
|
-
if (!options.
|
958
|
+
if (!options.userSwitching) {
|
959
|
+
// Keep groupId at -1 so that it's set to defaultGroup's GID.
|
960
|
+
} else if (!options.group.empty()) {
|
957
961
|
struct group *groupInfo = (struct group *) NULL;
|
958
962
|
|
959
963
|
if (options.group == "!STARTUP_FILE!") {
|
data/ext/common/Constants.h
CHANGED
@@ -110,7 +110,7 @@
|
|
110
110
|
|
111
111
|
#define NGINX_DOC_URL "https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html"
|
112
112
|
|
113
|
-
#define PASSENGER_VERSION "5.0.0.
|
113
|
+
#define PASSENGER_VERSION "5.0.0.beta2"
|
114
114
|
|
115
115
|
#define POOL_HELPER_THREAD_STACK_SIZE 262144
|
116
116
|
|
@@ -39,6 +39,9 @@ namespace ServerKit {
|
|
39
39
|
using namespace std;
|
40
40
|
|
41
41
|
|
42
|
+
extern const HashedStaticString HTTP_COOKIE;
|
43
|
+
extern const HashedStaticString HTTP_SET_COOKIE;
|
44
|
+
|
42
45
|
struct Header {
|
43
46
|
LString key;
|
44
47
|
LString val;
|
@@ -104,6 +107,18 @@ private:
|
|
104
107
|
return v;
|
105
108
|
}
|
106
109
|
|
110
|
+
OXT_FORCE_INLINE
|
111
|
+
static bool isCookieHeader(const Header *header) {
|
112
|
+
return header->hash == HTTP_COOKIE.hash()
|
113
|
+
&& psg_lstr_cmp(&header->key, HTTP_COOKIE);
|
114
|
+
}
|
115
|
+
|
116
|
+
OXT_FORCE_INLINE
|
117
|
+
static bool isSetCookieHeader(const Header *header) {
|
118
|
+
return header->hash == HTTP_SET_COOKIE.hash()
|
119
|
+
&& psg_lstr_cmp(&header->key, HTTP_SET_COOKIE);
|
120
|
+
}
|
121
|
+
|
107
122
|
void repopulate(unsigned int desiredSize) {
|
108
123
|
assert((desiredSize & (desiredSize - 1)) == 0); // Must be a power of 2
|
109
124
|
assert(m_population * 4 <= desiredSize * 3);
|
@@ -248,8 +263,13 @@ public:
|
|
248
263
|
return;
|
249
264
|
} else if (psg_lstr_cmp(&cell->header->key, &header->key)) {
|
250
265
|
// Cell matches, so merge value into header.
|
251
|
-
|
252
|
-
|
266
|
+
if (isCookieHeader(header)) {
|
267
|
+
psg_lstr_append(&cell->header->val, pool, ";", 1);
|
268
|
+
} else if (isSetCookieHeader(header)) {
|
269
|
+
psg_lstr_append(&cell->header->val, pool, "\n", 1);
|
270
|
+
} else {
|
271
|
+
psg_lstr_append(&cell->header->val, pool, ",", 1);
|
272
|
+
}
|
253
273
|
LString::Part *part = header->val.start;
|
254
274
|
header->val.start = NULL;
|
255
275
|
while (part != NULL) {
|
@@ -301,8 +321,12 @@ public:
|
|
301
321
|
if (PHT_CIRCULAR_OFFSET(ideal, cell) < PHT_CIRCULAR_OFFSET(ideal, neighbor)) {
|
302
322
|
// Erase current cell and move neighbor into this position,
|
303
323
|
// then make the now-empty neighbor the new cell to remove.
|
304
|
-
|
305
|
-
|
324
|
+
if (cell->header != NULL) {
|
325
|
+
// A previous iteration in this loop
|
326
|
+
// could have made cell->header NULL.
|
327
|
+
psg_lstr_deinit(&cell->header->key);
|
328
|
+
psg_lstr_deinit(&cell->header->val);
|
329
|
+
}
|
306
330
|
*cell = *neighbor;
|
307
331
|
cell = neighbor;
|
308
332
|
neighbor->header = NULL;
|
@@ -28,7 +28,9 @@ namespace Passenger {
|
|
28
28
|
namespace ServerKit {
|
29
29
|
|
30
30
|
|
31
|
-
extern
|
31
|
+
// Define 'extern' so that the compiler doesn't output warnings.
|
32
|
+
extern const HashedStaticString HTTP_COOKIE;
|
33
|
+
extern const HashedStaticString HTTP_SET_COOKIE;
|
32
34
|
extern const char DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE[];
|
33
35
|
extern const unsigned int DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE_SIZE;
|
34
36
|
|
@@ -41,6 +43,8 @@ const char DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE[] =
|
|
41
43
|
"Internal server error\n";
|
42
44
|
const unsigned int DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE_SIZE =
|
43
45
|
sizeof(DEFAULT_INTERNAL_SERVER_ERROR_RESPONSE) - 1;
|
46
|
+
const HashedStaticString HTTP_COOKIE("cookie");
|
47
|
+
const HashedStaticString HTTP_SET_COOKIE("set-cookie");
|
44
48
|
|
45
49
|
|
46
50
|
} // namespace ServerKit
|
@@ -939,12 +939,29 @@ preinitialize(VariantMap &options) {
|
|
939
939
|
}
|
940
940
|
}
|
941
941
|
|
942
|
+
static string
|
943
|
+
inferDefaultGroup(const string &defaultUser) {
|
944
|
+
struct passwd *userEntry = getpwnam(defaultUser.c_str());
|
945
|
+
if (userEntry == NULL) {
|
946
|
+
throw ConfigurationException(
|
947
|
+
string("The user that PassengerDefaultUser refers to, '") +
|
948
|
+
defaultUser + "', does not exist.");
|
949
|
+
}
|
950
|
+
return getGroupName(userEntry->pw_gid);
|
951
|
+
}
|
952
|
+
|
942
953
|
static void
|
943
954
|
setAgentsOptionsDefaults() {
|
944
955
|
VariantMap &options = *agentsOptions;
|
945
956
|
set<string> defaultAddress;
|
946
957
|
defaultAddress.insert(DEFAULT_HTTP_SERVER_LISTEN_ADDRESS);
|
947
958
|
|
959
|
+
options.setDefaultBool("user_switching", true);
|
960
|
+
options.setDefault("default_user", DEFAULT_WEB_APP_USER);
|
961
|
+
if (!options.has("default_group")) {
|
962
|
+
options.set("default_group",
|
963
|
+
inferDefaultGroup(options.get("default_user")));
|
964
|
+
}
|
948
965
|
options.setDefaultStrSet("server_addresses", defaultAddress);
|
949
966
|
options.setDefaultBool("multi_app", false);
|
950
967
|
options.setDefault("environment", DEFAULT_APP_ENV);
|
@@ -78,6 +78,12 @@ serverUsage() {
|
|
78
78
|
printf(" the given admin account. LEVEL indicates the\n");
|
79
79
|
printf(" privilege level (see below). PASSWORDFILE must\n");
|
80
80
|
printf(" point to a file containing the password\n");
|
81
|
+
printf(" --no-user-switching Disables user switching support\n");
|
82
|
+
printf(" --default-user NAME Default user to start apps as, when user\n");
|
83
|
+
printf(" switching is enabled. Default: " DEFAULT_WEB_APP_USER "\n");
|
84
|
+
printf(" --default-group NAME Default group to start apps as, when user\n");
|
85
|
+
printf(" switching is disabled. Default: the default\n");
|
86
|
+
printf(" user's primary group\n");
|
81
87
|
printf("\n");
|
82
88
|
printf("Application serving options (optional):\n");
|
83
89
|
printf(" -e, --environment NAME Default framework environment name to use.\n");
|
@@ -208,6 +214,15 @@ parseServerOption(int argc, const char *argv[], int &i, VariantMap &options) {
|
|
208
214
|
authorizations.push_back(argv[i + 1]);
|
209
215
|
options.setStrSet("server_authorizations", authorizations);
|
210
216
|
i += 2;
|
217
|
+
} else if (p.isFlag(argv[i], '\0', "--no-user-switching")) {
|
218
|
+
options.setBool("user_switching", false);
|
219
|
+
i++;
|
220
|
+
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--default-user")) {
|
221
|
+
options.set("default_user", argv[i + 1]);
|
222
|
+
i += 2;
|
223
|
+
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--default-group")) {
|
224
|
+
options.set("default_group", argv[i + 1]);
|
225
|
+
i += 2;
|
211
226
|
} else if (p.isValueFlag(argc, i, argv[i], '\0', "--max-pool-size")) {
|
212
227
|
options.setInt("max_pool_size", atoi(argv[i + 1]));
|
213
228
|
i += 2;
|
@@ -161,6 +161,12 @@ using namespace oxt;
|
|
161
161
|
using namespace ApplicationPool2;
|
162
162
|
|
163
163
|
|
164
|
+
namespace ServerKit {
|
165
|
+
extern const HashedStaticString HTTP_COOKIE;
|
166
|
+
extern const HashedStaticString HTTP_SET_COOKIE;
|
167
|
+
}
|
168
|
+
|
169
|
+
|
164
170
|
class RequestHandler: public ServerKit::HttpServer<RequestHandler, Client> {
|
165
171
|
public:
|
166
172
|
enum BenchmarkMode {
|
@@ -300,6 +300,22 @@ onAppResponseBegin(Client *client, Request *req) {
|
|
300
300
|
// Localize hash table operations for better CPU caching.
|
301
301
|
oobw = resp->secureHeaders.lookup(PASSENGER_REQUEST_OOB_WORK) != NULL;
|
302
302
|
resp->date = resp->headers.lookup(HTTP_DATE);
|
303
|
+
resp->setCookie = resp->headers.lookup(ServerKit::HTTP_SET_COOKIE);
|
304
|
+
if (resp->setCookie != NULL) {
|
305
|
+
// Remove Set-Cookie from resp->headers without deallocating it.
|
306
|
+
LString *copy;
|
307
|
+
|
308
|
+
copy = (LString *) psg_palloc(req->pool, sizeof(LString));
|
309
|
+
*copy = *resp->setCookie;
|
310
|
+
|
311
|
+
resp->setCookie->start = NULL;
|
312
|
+
resp->setCookie->end = NULL;
|
313
|
+
resp->setCookie->size = 0;
|
314
|
+
psg_lstr_append(resp->setCookie, req->pool, "x", 1);
|
315
|
+
resp->headers.erase(ServerKit::HTTP_SET_COOKIE);
|
316
|
+
|
317
|
+
resp->setCookie = copy;
|
318
|
+
}
|
303
319
|
resp->headers.erase(HTTP_CONNECTION);
|
304
320
|
resp->headers.erase(HTTP_STATUS);
|
305
321
|
if (resp->bodyType == AppResponse::RBT_CONTENT_LENGTH) {
|
@@ -574,6 +590,26 @@ constructHeaderBuffersForResponse(Request *req, struct iovec *buffers,
|
|
574
590
|
PUSH_STATIC_BUFFER("\r\n");
|
575
591
|
}
|
576
592
|
|
593
|
+
if (resp->setCookie != NULL) {
|
594
|
+
PUSH_STATIC_BUFFER("Set-Cookie: ");
|
595
|
+
part = resp->setCookie->start;
|
596
|
+
while (part != NULL) {
|
597
|
+
if (part->size == 1 && part->data[0] == '\n') {
|
598
|
+
// HeaderTable joins multiple Set-Cookie headers together using \n.
|
599
|
+
PUSH_STATIC_BUFFER("\r\nSet-Cookie: ");
|
600
|
+
} else {
|
601
|
+
if (buffers != NULL) {
|
602
|
+
buffers[i].iov_base = (void *) part->data;
|
603
|
+
buffers[i].iov_len = part->size;
|
604
|
+
}
|
605
|
+
INC_BUFFER_ITER(i);
|
606
|
+
dataSize += part->size;
|
607
|
+
}
|
608
|
+
part = part->next;
|
609
|
+
}
|
610
|
+
PUSH_STATIC_BUFFER("\r\n");
|
611
|
+
}
|
612
|
+
|
577
613
|
nCacheableBuffers = i;
|
578
614
|
|
579
615
|
if (resp->bodyType == AppResponse::RBT_CONTENT_LENGTH) {
|
@@ -137,6 +137,7 @@ void reinitializeAppResponse(Client *client, Request *req) {
|
|
137
137
|
resp->aux.bodyInfo.contentLength = 0; // Sets the entire union to 0.
|
138
138
|
resp->bodyAlreadyRead = 0;
|
139
139
|
resp->date = NULL;
|
140
|
+
resp->setCookie = NULL;
|
140
141
|
resp->cacheControl = NULL;
|
141
142
|
resp->expiresHeader = NULL;
|
142
143
|
resp->lastModifiedHeader = NULL;
|
@@ -206,11 +206,12 @@ fillPoolOptionsFromAgentsOptions(Options &options) {
|
|
206
206
|
options.loggingAgentAddress = loggingAgentAddress;
|
207
207
|
options.loggingAgentUsername = P_STATIC_STRING("logging");
|
208
208
|
options.loggingAgentPassword = loggingAgentPassword;
|
209
|
-
|
210
|
-
|
209
|
+
options.userSwitching = agentsOptions->getBool("user_switching");
|
210
|
+
if (agentsOptions->has("default_user")) {
|
211
|
+
options.defaultUser = agentsOptions->get("default_user");
|
211
212
|
}
|
212
|
-
if (
|
213
|
-
options.defaultGroup =
|
213
|
+
if (agentsOptions->has("default_group")) {
|
214
|
+
options.defaultGroup = agentsOptions->get("default_group");
|
214
215
|
}
|
215
216
|
options.minProcesses = agentsOptions->getInt("min_instances");
|
216
217
|
options.spawnMethod = agentsOptions->get("spawn_method");
|
@@ -478,6 +478,7 @@ httpHeaderToScgiUpperCase(unsigned char *data, unsigned int size) {
|
|
478
478
|
struct HttpHeaderConstructionCache {
|
479
479
|
StaticString methodStr;
|
480
480
|
const LString *remoteAddr;
|
481
|
+
const LString *setCookie;
|
481
482
|
bool cached;
|
482
483
|
};
|
483
484
|
|
@@ -568,6 +569,7 @@ constructHeaderBuffersForHttpProtocol(Request *req, struct iovec *buffers,
|
|
568
569
|
if (!cache.cached) {
|
569
570
|
cache.methodStr = http_method_str(req->method);
|
570
571
|
cache.remoteAddr = req->secureHeaders.lookup(REMOTE_ADDR);
|
572
|
+
cache.setCookie = req->headers.lookup(ServerKit::HTTP_SET_COOKIE);
|
571
573
|
cache.cached = true;
|
572
574
|
}
|
573
575
|
|
@@ -593,9 +595,33 @@ constructHeaderBuffersForHttpProtocol(Request *req, struct iovec *buffers,
|
|
593
595
|
PUSH_STATIC_BUFFER(" HTTP/1.1\r\nConnection: close\r\n");
|
594
596
|
}
|
595
597
|
|
598
|
+
if (cache.setCookie != NULL) {
|
599
|
+
LString::Part *part;
|
600
|
+
|
601
|
+
PUSH_STATIC_BUFFER("Set-Cookie: ");
|
602
|
+
part = cache.setCookie->start;
|
603
|
+
while (part != NULL) {
|
604
|
+
if (part->size == 1 && part->data[0] == '\n') {
|
605
|
+
// HeaderTable joins multiple Set-Cookie headers together using \n.
|
606
|
+
PUSH_STATIC_BUFFER("\r\nSet-Cookie: ");
|
607
|
+
} else {
|
608
|
+
if (buffers != NULL) {
|
609
|
+
buffers[i].iov_base = (void *) part->data;
|
610
|
+
buffers[i].iov_len = part->size;
|
611
|
+
}
|
612
|
+
INC_BUFFER_ITER(i);
|
613
|
+
dataSize += part->size;
|
614
|
+
}
|
615
|
+
part = part->next;
|
616
|
+
}
|
617
|
+
PUSH_STATIC_BUFFER("\r\n");
|
618
|
+
}
|
619
|
+
|
596
620
|
while (*it != NULL) {
|
597
|
-
if (it->header->hash == HTTP_CONNECTION.hash()
|
598
|
-
|
621
|
+
if ((it->header->hash == HTTP_CONNECTION.hash()
|
622
|
+
|| it->header->hash == ServerKit::HTTP_SET_COOKIE.hash())
|
623
|
+
&& (psg_lstr_cmp(&it->header->key, P_STATIC_STRING("connection"))
|
624
|
+
|| psg_lstr_cmp(&it->header->key, ServerKit::HTTP_SET_COOKIE)))
|
599
625
|
{
|
600
626
|
it.next();
|
601
627
|
continue;
|
@@ -460,7 +460,7 @@ public:
|
|
460
460
|
|
461
461
|
// @pre prepareRequest() returned true
|
462
462
|
bool requestAllowsFetching(Request *req) const {
|
463
|
-
return req->method == HTTP_GET
|
463
|
+
return (req->method == HTTP_GET || req->method == HTTP_HEAD)
|
464
464
|
&& req->cacheControl == NULL
|
465
465
|
&& !req->hasPragmaHeader;
|
466
466
|
}
|
data/ext/ruby/extconf.rb
CHANGED
@@ -37,8 +37,10 @@ end
|
|
37
37
|
have_header('alloca.h')
|
38
38
|
have_header('ruby/version.h')
|
39
39
|
have_header('ruby/io.h')
|
40
|
+
have_header('ruby/thread.h')
|
40
41
|
have_var('ruby_version')
|
41
42
|
have_func('rb_thread_io_blocking_region')
|
43
|
+
have_func('rb_thread_call_without_gvl')
|
42
44
|
|
43
45
|
with_cflags($CFLAGS) do
|
44
46
|
create_makefile('passenger_native_support')
|
@@ -36,6 +36,9 @@
|
|
36
36
|
#ifdef HAVE_RUBY_VERSION_H
|
37
37
|
#include "ruby/version.h"
|
38
38
|
#endif
|
39
|
+
#ifdef HAVE_RUBY_THREAD_H
|
40
|
+
#include "ruby/thread.h"
|
41
|
+
#endif
|
39
42
|
#include <sys/types.h>
|
40
43
|
#include <sys/stat.h>
|
41
44
|
#include <sys/ioctl.h>
|
@@ -199,11 +202,19 @@ update_group_written_info(IOVectorGroup *group, ssize_t bytes_written) {
|
|
199
202
|
int iovcnt;
|
200
203
|
} WritevWrapperData;
|
201
204
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
205
|
+
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
206
|
+
static void *
|
207
|
+
writev_wrapper(void *ptr) {
|
208
|
+
WritevWrapperData *data = (WritevWrapperData *) ptr;
|
209
|
+
return (void *) writev(data->filedes, data->iov, data->iovcnt);
|
210
|
+
}
|
211
|
+
#else
|
212
|
+
static VALUE
|
213
|
+
writev_wrapper(void *ptr) {
|
214
|
+
WritevWrapperData *data = (WritevWrapperData *) ptr;
|
215
|
+
return (VALUE) writev(data->filedes, data->iov, data->iovcnt);
|
216
|
+
}
|
217
|
+
#endif
|
207
218
|
#endif
|
208
219
|
|
209
220
|
static VALUE
|
@@ -320,7 +331,10 @@ f_generic_writev(VALUE fd, VALUE *array_of_components, unsigned int count) {
|
|
320
331
|
writev_wrapper_data.filedes = fd_num;
|
321
332
|
writev_wrapper_data.iov = groups[i].io_vectors;
|
322
333
|
writev_wrapper_data.iovcnt = groups[i].count;
|
323
|
-
#
|
334
|
+
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
335
|
+
ret = (int) rb_thread_call_without_gvl(writev_wrapper,
|
336
|
+
&writev_wrapper_data, RUBY_UBF_IO, NULL);
|
337
|
+
#elif defined(HAVE_RB_THREAD_IO_BLOCKING_REGION)
|
324
338
|
ret = (int) rb_thread_io_blocking_region(writev_wrapper,
|
325
339
|
&writev_wrapper_data, fd_num);
|
326
340
|
#else
|
@@ -726,13 +740,23 @@ fs_watcher_wait_fd(VALUE _fd) {
|
|
726
740
|
}
|
727
741
|
|
728
742
|
#ifndef TRAP_BEG
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
743
|
+
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
744
|
+
static void *
|
745
|
+
fs_watcher_read_byte_from_fd_wrapper(void *_arg) {
|
746
|
+
FSWatcherReadByteData *data = (FSWatcherReadByteData *) _arg;
|
747
|
+
data->ret = read(data->fd, &data->byte, 1);
|
748
|
+
data->error = errno;
|
749
|
+
return NULL;
|
750
|
+
}
|
751
|
+
#else
|
752
|
+
static VALUE
|
753
|
+
fs_watcher_read_byte_from_fd_wrapper(void *_arg) {
|
754
|
+
FSWatcherReadByteData *data = (FSWatcherReadByteData *) _arg;
|
755
|
+
data->ret = read(data->fd, &data->byte, 1);
|
756
|
+
data->error = errno;
|
757
|
+
return Qnil;
|
758
|
+
}
|
759
|
+
#endif
|
736
760
|
#endif
|
737
761
|
|
738
762
|
static VALUE
|
@@ -743,6 +767,9 @@ fs_watcher_read_byte_from_fd(VALUE _arg) {
|
|
743
767
|
data->ret = read(data->fd, &data->byte, 1);
|
744
768
|
TRAP_END;
|
745
769
|
data->error = errno;
|
770
|
+
#elif defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
771
|
+
rb_thread_call_without_gvl2(fs_watcher_read_byte_from_fd_wrapper,
|
772
|
+
data, RUBY_UBF_IO, NULL);
|
746
773
|
#elif defined(HAVE_RB_THREAD_IO_BLOCKING_REGION)
|
747
774
|
rb_thread_io_blocking_region(fs_watcher_read_byte_from_fd_wrapper,
|
748
775
|
data, data->fd);
|
data/lib/phusion_passenger.rb
CHANGED
@@ -30,7 +30,7 @@ module PhusionPassenger
|
|
30
30
|
|
31
31
|
PACKAGE_NAME = 'passenger'
|
32
32
|
# Run 'rake ext/common/Constants.h' after changing this number.
|
33
|
-
VERSION_STRING = '5.0.0.
|
33
|
+
VERSION_STRING = '5.0.0.beta2'
|
34
34
|
|
35
35
|
PREFERRED_NGINX_VERSION = '1.6.2'
|
36
36
|
NGINX_SHA256_CHECKSUM = 'b5608c2959d3e7ad09b20fc8f9e5bd4bc87b3bc8ba5936a513c04ed8f1391a18'
|
@@ -81,11 +81,11 @@ private
|
|
81
81
|
opts.on("-i", "--stdin", "Read HTTP request body data from stdin") do
|
82
82
|
options[:data_source] = :stdin
|
83
83
|
end
|
84
|
-
opts.on("-f", "--data-file", String, "Read HTTP request body data from the given#{nl}" +
|
84
|
+
opts.on("-f", "--data-file PATH", String, "Read HTTP request body data from the given#{nl}" +
|
85
85
|
"file") do |value|
|
86
86
|
options[:data_source] = value
|
87
87
|
end
|
88
|
-
opts.on("-a", "--agent", String, "The name of the socket to send the command#{nl}" +
|
88
|
+
opts.on("-a", "--agent NAME", String, "The name of the socket to send the command#{nl}" +
|
89
89
|
"to. This specifies which agent the request#{nl}" +
|
90
90
|
"is sent to. Choices: watchdog,#{nl}" +
|
91
91
|
"server_admin, logging_admin.#{nl}" +
|
@@ -101,7 +101,7 @@ module Config
|
|
101
101
|
puts "#{PROGRAM_NAME} installation management:"
|
102
102
|
puts " validate-install Validate this #{PROGRAM_NAME} installation"
|
103
103
|
puts " build-native-support Ensure that the native_support library for the current"
|
104
|
-
puts " Ruby
|
104
|
+
puts " Ruby interpreter is built"
|
105
105
|
puts " install-agent Install the #{PROGRAM_NAME} agent binary"
|
106
106
|
puts " install-standalone-runtime"
|
107
107
|
puts " Install the #{PROGRAM_NAME} Standalone"
|
@@ -29,8 +29,13 @@ module Config
|
|
29
29
|
|
30
30
|
class SystemMetricsCommand < Command
|
31
31
|
def run
|
32
|
-
|
33
|
-
|
32
|
+
agent_exe = PhusionPassenger.find_support_binary(AGENT_EXE)
|
33
|
+
if agent_exe
|
34
|
+
exec(agent_exe, "system-metrics", *@argv)
|
35
|
+
else
|
36
|
+
abort "This command requires the #{PROGRAM_NAME} agent to be installed. " +
|
37
|
+
"Please install it by running `passenger-config install-agent`."
|
38
|
+
end
|
34
39
|
end
|
35
40
|
end
|
36
41
|
|
@@ -34,14 +34,14 @@ module PlatformInfo
|
|
34
34
|
def self.os_name
|
35
35
|
if rb_config['target_os'] =~ /darwin/ && (sw_vers = find_command('sw_vers'))
|
36
36
|
return "macosx"
|
37
|
-
elsif rb_config['target_os']
|
37
|
+
elsif rb_config['target_os'] =~ /^linux-/
|
38
38
|
return "linux"
|
39
39
|
else
|
40
40
|
return rb_config['target_os']
|
41
41
|
end
|
42
42
|
end
|
43
43
|
memoize :os_name
|
44
|
-
|
44
|
+
|
45
45
|
# The current platform's shared library extension ('so' on most Unices).
|
46
46
|
def self.library_extension
|
47
47
|
if os_name == "macosx"
|
@@ -50,7 +50,7 @@ module PlatformInfo
|
|
50
50
|
return "so"
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# Returns the `uname` command, or nil if `uname` cannot be found.
|
55
55
|
# In addition to looking for `uname` in `PATH`, this method also looks
|
56
56
|
# for `uname` in /bin and /usr/bin, just in case the user didn't
|
@@ -129,7 +129,7 @@ module PlatformInfo
|
|
129
129
|
elsif arch == "amd64"
|
130
130
|
arch = "x86_64"
|
131
131
|
end
|
132
|
-
|
132
|
+
|
133
133
|
if arch == "x86"
|
134
134
|
# Most x86 operating systems nowadays are probably running on
|
135
135
|
# a CPU that supports both x86 and x86_64, but we're not gonna
|
@@ -146,7 +146,7 @@ module PlatformInfo
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
memoize :cpu_architectures, true
|
149
|
-
|
149
|
+
|
150
150
|
# Returns whether the OS's main CPU architecture supports the
|
151
151
|
# x86/x86_64 sfence instruction.
|
152
152
|
def self.supports_sfence_instruction?
|
@@ -161,7 +161,7 @@ module PlatformInfo
|
|
161
161
|
}))
|
162
162
|
end
|
163
163
|
memoize :supports_sfence_instruction?, true
|
164
|
-
|
164
|
+
|
165
165
|
# Returns whether the OS's main CPU architecture supports the
|
166
166
|
# x86/x86_64 lfence instruction.
|
167
167
|
def self.supports_lfence_instruction?
|
@@ -21,6 +21,7 @@
|
|
21
21
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
22
|
# THE SOFTWARE.
|
23
23
|
|
24
|
+
require 'etc'
|
24
25
|
PhusionPassenger.require_passenger_lib 'constants'
|
25
26
|
PhusionPassenger.require_passenger_lib 'standalone/control_utils'
|
26
27
|
PhusionPassenger.require_passenger_lib 'utils/shellwords'
|
@@ -66,6 +67,7 @@ private
|
|
66
67
|
command = "#{@agent_exe} watchdog";
|
67
68
|
command << " --passenger-root #{Shellwords.escape PhusionPassenger.install_spec}"
|
68
69
|
command << " --daemonize"
|
70
|
+
command << " --no-user-switching"
|
69
71
|
command << " --no-delete-pid-file"
|
70
72
|
command << " --cleanup-pidfile #{Shellwords.escape @working_dir}/temp_dir_toucher.pid"
|
71
73
|
add_param(command, :user, "--user")
|
@@ -77,6 +79,14 @@ private
|
|
77
79
|
@options[:ctls].each do |ctl|
|
78
80
|
command << " --ctl #{Shellwords.escape ctl}"
|
79
81
|
end
|
82
|
+
if @options[:user]
|
83
|
+
command << " --default-user #{Shellwords.ecape @options[:user]}"
|
84
|
+
else
|
85
|
+
user = Etc.getpwuid(Process.uid).name
|
86
|
+
group = Etc.getgrgid(Process.gid).name
|
87
|
+
command << " --default-user #{Shellwords.escape user}"
|
88
|
+
command << " --default-group #{Shellwords.escape group}"
|
89
|
+
end
|
80
90
|
|
81
91
|
command << " --BS"
|
82
92
|
command << " --listen #{listen_address}"
|
@@ -100,7 +110,7 @@ private
|
|
100
110
|
add_param(command, :max_pool_size, "--max-pool-size")
|
101
111
|
add_param(command, :min_instances, "--min-instances")
|
102
112
|
add_enterprise_param(command, :concurrency_model, "--concurrency-model")
|
103
|
-
add_enterprise_param(command, :thread_count, "--thread-count")
|
113
|
+
add_enterprise_param(command, :thread_count, "--app-thread-count")
|
104
114
|
add_enterprise_flag_param(command, :rolling_restarts, "--rolling-restarts")
|
105
115
|
add_enterprise_flag_param(command, :resist_deployment_errors, "--resist-deployment-errors")
|
106
116
|
add_flag_param(command, :sticky_sessions, "--sticky-sessions")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2012-
|
3
|
+
* Copyright (c) 2012-2014 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -44,6 +44,8 @@ function LineReader(stream) {
|
|
44
44
|
this.paused = false;
|
45
45
|
|
46
46
|
function handleLineBuffer() {
|
47
|
+
var line, callback;
|
48
|
+
|
47
49
|
if (self.lineBufferIsFull()) {
|
48
50
|
stream.pause();
|
49
51
|
self.paused = true;
|
@@ -163,9 +163,15 @@ namespace tut {
|
|
163
163
|
table.insert(createHeader("X-Forwarded-For", "bar.com"), pool);
|
164
164
|
table.insert(createHeader("Cache-Control", "must-invalidate"), pool);
|
165
165
|
table.insert(createHeader("Cache-Control", "private"), pool);
|
166
|
+
table.insert(createHeader("cookie", "a"), pool);
|
167
|
+
table.insert(createHeader("cookie", "b"), pool);
|
168
|
+
table.insert(createHeader("set-cookie", "c=123"), pool);
|
169
|
+
table.insert(createHeader("set-cookie", "d=456"), pool);
|
166
170
|
|
167
|
-
ensure_equals(table.size(),
|
171
|
+
ensure_equals(table.size(), 4u);
|
168
172
|
ensure("(1)", psg_lstr_cmp(table.lookup("X-Forwarded-For"), "foo.com,bar.com"));
|
169
173
|
ensure("(2)", psg_lstr_cmp(table.lookup("Cache-Control"), "must-invalidate,private"));
|
174
|
+
ensure("(3)", psg_lstr_cmp(table.lookup("cookie"), "a;b"));
|
175
|
+
ensure("(4)", psg_lstr_cmp(table.lookup("set-cookie"), "c=123\nd=456"));
|
170
176
|
}
|
171
177
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passenger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.0.
|
4
|
+
version: 5.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Phusion - http://www.phusion.nl/
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
metadata.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
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
=
|
5
|
+
iQEcBAABAgAGBQJUlA2PAAoJECrHRaUKISqMr/wH/32meSRiPtVaiDcVmbacmRXn
|
6
|
+
iZ7KrTWZ1PqA03DpZBSDc/aZmpIQCR/kbt/Ozq5bEar102V8XuJ9iM9l4LNeiRBx
|
7
|
+
iOXAj2/F8hRAR4eUPjNeMmrDFnoGF250aBTSjzr846DQZGUxB3PwDIPxeKMS96ek
|
8
|
+
eD70rQ5BYzb1yfsxgcRMnSEQtjGv5je+t13c7gjwfERhpkBPquEA5rboQYRnyCsD
|
9
|
+
5ujz+VM3Tf04QMGQy66V9KiRa99BwuzkUaX62qpHdPB6K97f+2729nR0duY3pH6+
|
10
|
+
MY2XYKut8R0XIR+J9Ho6M0lHWASytT4huFDRmF7th2uxPCI2NdOg0fmdG3gyTyo=
|
11
|
+
=2PDq
|
12
12
|
-----END PGP SIGNATURE-----
|