passenger 5.0.0.beta2 → 5.0.0.beta3
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 +30 -0
- data/CONTRIBUTORS +2 -0
- data/Gemfile.lock +1 -1
- data/bin/passenger-status +13 -15
- data/build/cxx_tests.rb +14 -1
- data/build/preprocessor.rb +4 -2
- data/debian.template/control.template +2 -2
- data/doc/Security of user switching support.txt +2 -2
- data/doc/Users guide Apache.idmap.txt +6 -4
- data/doc/Users guide Apache.txt +20 -1
- data/doc/Users guide Nginx.idmap.txt +5 -3
- data/doc/Users guide Nginx.txt +22 -2
- data/ext/apache2/Configuration.cpp +6 -0
- data/ext/apache2/Configuration.hpp +4 -1
- data/ext/apache2/Hooks.cpp +1 -0
- data/ext/common/Constants.h +4 -2
- data/ext/common/Constants.h.erb +1 -1
- data/ext/common/DataStructures/LString.h +10 -0
- data/ext/common/ServerKit/Channel.h +1 -1
- data/ext/common/ServerKit/Context.h +2 -21
- data/ext/common/ServerKit/CookieUtils.h +246 -0
- data/ext/common/ServerKit/FdSourceChannel.h +10 -0
- data/ext/common/ServerKit/FileBufferedChannel.h +173 -17
- data/ext/common/ServerKit/FileBufferedFdSinkChannel.h +33 -1
- data/ext/common/ServerKit/HeaderTable.h +3 -1
- data/ext/common/ServerKit/HttpServer.h +36 -8
- data/ext/common/ServerKit/Server.h +1 -0
- data/ext/common/Utils.cpp +2 -1
- data/ext/common/Utils/DateParsing.h +15 -2
- data/ext/common/Utils/JsonUtils.h +39 -1
- data/ext/common/agents/HelperAgent/Main.cpp +4 -2
- data/ext/common/agents/HelperAgent/OptionParser.h +14 -2
- data/ext/common/agents/HelperAgent/RequestHandler.h +22 -8
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +92 -11
- data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +3 -1
- data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +9 -5
- data/ext/common/agents/HelperAgent/RequestHandler/Request.h +1 -0
- data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +27 -13
- data/ext/common/agents/HelperAgent/ResponseCache.h +91 -34
- data/ext/common/agents/LoggingAgent/AdminServer.h +21 -1
- data/ext/nginx/CacheLocationConfig.c +20 -0
- data/ext/nginx/Configuration.c +130 -24
- data/ext/nginx/Configuration.h +2 -1
- data/ext/nginx/ConfigurationCommands.c +10 -0
- data/ext/nginx/ConfigurationFields.h +2 -0
- data/ext/nginx/ContentHandler.c +1 -6
- data/ext/nginx/CreateLocationConfig.c +5 -0
- data/ext/nginx/MergeLocationConfig.c +6 -0
- data/ext/nginx/StaticContentHandler.c +3 -9
- data/ext/nginx/ngx_http_passenger_module.c +2 -1
- data/ext/ruby/extconf.rb +5 -4
- data/lib/phusion_passenger.rb +2 -2
- data/lib/phusion_passenger/constants.rb +2 -1
- data/lib/phusion_passenger/nginx/config_options.rb +5 -1
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +3 -1
- data/lib/phusion_passenger/ruby_core_enhancements.rb +3 -4
- data/lib/phusion_passenger/standalone/start_command.rb +5 -1
- data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +10 -3
- data/resources/templates/standalone/config.erb +2 -1
- data/test/cxx/DateParsingTest.cpp +75 -0
- data/test/cxx/ResponseCacheTest.cpp +322 -0
- data/test/cxx/ServerKit/CookieUtilsTest.cpp +274 -0
- data/test/cxx/ServerKit/HttpServerTest.cpp +77 -0
- data/test/stub/rails3.0/Gemfile.lock +2 -2
- data/test/stub/rails3.1/Gemfile.lock +2 -2
- data/test/stub/rails3.2/Gemfile.lock +2 -2
- data/test/stub/rails4.0/Gemfile.lock +2 -2
- data/test/stub/rails4.1/Gemfile.lock +2 -2
- metadata +6 -2
- metadata.gz.asc +7 -7
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* Copyright (C) Igor Sysoev
|
3
3
|
* Copyright (C) 2007 Manlio Perillo (manlio.perillo@gmail.com)
|
4
|
-
* Copyright (C) 2010-
|
4
|
+
* Copyright (C) 2010-2015 Phusion
|
5
5
|
*
|
6
6
|
* Redistribution and use in source and binary forms, with or without
|
7
7
|
* modification, are permitted provided that the following conditions
|
@@ -289,6 +289,7 @@ start_watchdog(ngx_cycle_t *cycle) {
|
|
289
289
|
pp_variant_map_set_ngx_str(params, "default_ruby", &passenger_main_conf.default_ruby);
|
290
290
|
pp_variant_map_set_int (params, "max_pool_size", passenger_main_conf.max_pool_size);
|
291
291
|
pp_variant_map_set_int (params, "pool_idle_time", passenger_main_conf.pool_idle_time);
|
292
|
+
pp_variant_map_set_int (params, "response_buffer_high_watermark", passenger_main_conf.response_buffer_high_watermark);
|
292
293
|
pp_variant_map_set_int (params, "stat_throttle_rate", passenger_main_conf.stat_throttle_rate);
|
293
294
|
pp_variant_map_set_ngx_str(params, "analytics_log_user", &passenger_main_conf.analytics_log_user);
|
294
295
|
pp_variant_map_set_ngx_str(params, "analytics_log_group", &passenger_main_conf.analytics_log_group);
|
data/ext/ruby/extconf.rb
CHANGED
@@ -21,9 +21,9 @@
|
|
21
21
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
22
|
# THE SOFTWARE.
|
23
23
|
require 'mkmf'
|
24
|
-
|
24
|
+
|
25
|
+
$LIBS << " -lpthread" if $LIBS !~ /-lpthread/
|
25
26
|
$CFLAGS << " -g"
|
26
|
-
$LIBS << " -lpthread"
|
27
27
|
|
28
28
|
if RUBY_PLATFORM =~ /solaris/
|
29
29
|
have_library('xnet')
|
@@ -39,8 +39,8 @@ have_header('ruby/version.h')
|
|
39
39
|
have_header('ruby/io.h')
|
40
40
|
have_header('ruby/thread.h')
|
41
41
|
have_var('ruby_version')
|
42
|
-
have_func('rb_thread_io_blocking_region')
|
43
|
-
have_func('rb_thread_call_without_gvl')
|
42
|
+
have_func('rb_thread_io_blocking_region', 'ruby/io.h')
|
43
|
+
have_func('rb_thread_call_without_gvl', 'ruby/thread.h')
|
44
44
|
|
45
45
|
with_cflags($CFLAGS) do
|
46
46
|
create_makefile('passenger_native_support')
|
@@ -64,3 +64,4 @@ with_cflags($CFLAGS) do
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
67
|
+
|
data/lib/phusion_passenger.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
# Copyright (c) 2010-
|
3
|
+
# Copyright (c) 2010-2015 Phusion
|
4
4
|
#
|
5
5
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
#
|
@@ -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.beta3'
|
34
34
|
|
35
35
|
PREFERRED_NGINX_VERSION = '1.6.2'
|
36
36
|
NGINX_SHA256_CHECKSUM = 'b5608c2959d3e7ad09b20fc8f9e5bd4bc87b3bc8ba5936a513c04ed8f1391a18'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
2
|
-
# Copyright (c) 2010-
|
2
|
+
# Copyright (c) 2010-2015 Phusion
|
3
3
|
#
|
4
4
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
5
5
|
#
|
@@ -56,6 +56,7 @@ module PhusionPassenger
|
|
56
56
|
DEFAULT_CONCURRENCY_MODEL = "process"
|
57
57
|
DEFAULT_STICKY_SESSIONS_COOKIE_NAME = "_passenger_route"
|
58
58
|
DEFAULT_APP_THREAD_COUNT = 1
|
59
|
+
DEFAULT_RESPONSE_BUFFER_HIGH_WATERMARK = 1024 * 1024 * 128
|
59
60
|
DEFAULT_STAT_THROTTLE_RATE = 10
|
60
61
|
DEFAULT_ANALYTICS_LOG_USER = DEFAULT_WEB_APP_USER
|
61
62
|
DEFAULT_ANALYTICS_LOG_GROUP = ""
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
2
|
-
# Copyright (c) 2013-
|
2
|
+
# Copyright (c) 2013-2015 Phusion
|
3
3
|
#
|
4
4
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
5
5
|
#
|
@@ -297,6 +297,10 @@ LOCATION_CONFIGURATION_OPTIONS = [
|
|
297
297
|
:name => 'passenger_sticky_sessions_cookie_name',
|
298
298
|
:type => :string
|
299
299
|
},
|
300
|
+
{
|
301
|
+
:name => 'passenger_vary_turbocache_by_cookie',
|
302
|
+
:type => :string
|
303
|
+
},
|
300
304
|
|
301
305
|
###### Enterprise features ######
|
302
306
|
{
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: binary
|
2
2
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
# Copyright (c) 2010-
|
3
|
+
# Copyright (c) 2010-2015 Phusion
|
4
4
|
#
|
5
5
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
#
|
@@ -207,6 +207,8 @@ private
|
|
207
207
|
# We do not check for this key name in every loop
|
208
208
|
# iteration as an optimization.
|
209
209
|
next
|
210
|
+
else
|
211
|
+
values = values.to_s.split(NEWLINE)
|
210
212
|
end
|
211
213
|
values.each do |value|
|
212
214
|
result << key
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: binary
|
2
2
|
# Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
# Copyright (c) 2010-
|
3
|
+
# Copyright (c) 2010-2015 Phusion
|
4
4
|
#
|
5
5
|
# "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
#
|
@@ -96,17 +96,16 @@ module Signal
|
|
96
96
|
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
|
97
97
|
case ruby_engine
|
98
98
|
when "jruby"
|
99
|
-
result = Signal.list
|
99
|
+
result = Signal.list.dup
|
100
100
|
result.delete("QUIT")
|
101
101
|
result.delete("ILL")
|
102
102
|
result.delete("FPE")
|
103
|
-
result.delete("KILL")
|
104
103
|
result.delete("SEGV")
|
105
104
|
result.delete("USR1")
|
106
105
|
result.delete("IOT")
|
107
106
|
result.delete("EXIT")
|
108
107
|
else
|
109
|
-
result = Signal.list
|
108
|
+
result = Signal.list.dup
|
110
109
|
result.delete("ALRM")
|
111
110
|
result.delete("VTALRM")
|
112
111
|
end
|
@@ -241,11 +241,15 @@ private
|
|
241
241
|
opts.on("--sticky-sessions", "Enable sticky sessions") do
|
242
242
|
options[:sticky_sessions] = true
|
243
243
|
end
|
244
|
-
opts.on("--sticky-sessions-cookie-name", String,
|
244
|
+
opts.on("--sticky-sessions-cookie-name NAME", String,
|
245
245
|
"Cookie name to use for sticky sessions.#{nl}" +
|
246
246
|
"Default: #{DEFAULT_STICKY_SESSIONS_COOKIE_NAME}") do |value|
|
247
247
|
options[:sticky_sessions_cookie_name] = value
|
248
248
|
end
|
249
|
+
opts.on("--vary-turbocache-by-cookie NAME", String,
|
250
|
+
"Vary the turbocache by the cookie of the given name") do |value|
|
251
|
+
options[:vary_turbocache_by_cookie] = value
|
252
|
+
end
|
249
253
|
opts.on("--disable-turbocaching", "Disable turbocaching") do
|
250
254
|
options[:turbocaching] = false
|
251
255
|
end
|
@@ -80,12 +80,18 @@ private
|
|
80
80
|
command << " --ctl #{Shellwords.escape ctl}"
|
81
81
|
end
|
82
82
|
if @options[:user]
|
83
|
-
command << " --default-user #{Shellwords.
|
83
|
+
command << " --default-user #{Shellwords.escape @options[:user]}"
|
84
84
|
else
|
85
85
|
user = Etc.getpwuid(Process.uid).name
|
86
|
-
|
86
|
+
begin
|
87
|
+
group = Etc.getgrgid(Process.gid)
|
88
|
+
rescue ArgumentError
|
89
|
+
# Do nothing. On Heroku, it's normal that the group
|
90
|
+
# database is broken.
|
91
|
+
else
|
92
|
+
command << " --default-group #{Shellwords.escape group.name}"
|
93
|
+
end
|
87
94
|
command << " --default-user #{Shellwords.escape user}"
|
88
|
-
command << " --default-group #{Shellwords.escape group}"
|
89
95
|
end
|
90
96
|
|
91
97
|
command << " --BS"
|
@@ -114,6 +120,7 @@ private
|
|
114
120
|
add_enterprise_flag_param(command, :rolling_restarts, "--rolling-restarts")
|
115
121
|
add_enterprise_flag_param(command, :resist_deployment_errors, "--resist-deployment-errors")
|
116
122
|
add_flag_param(command, :sticky_sessions, "--sticky-sessions")
|
123
|
+
add_param(command, :vary_turbocache_by_cookie, "--vary-turbocache-by-cookie")
|
117
124
|
add_param(command, :sticky_sessions_cookie_name, "--sticky-sessions-cookie-name")
|
118
125
|
add_param(command, :union_station_gateway_address, "--union-station-gateway-address")
|
119
126
|
add_param(command, :union_station_gateway_port, "--union-station-gateway-port")
|
@@ -140,7 +140,8 @@ http {
|
|
140
140
|
<% if app[:min_instances] %>passenger_min_instances <%= app[:min_instances] %>;<% end %>
|
141
141
|
<% if app[:restart_dir] %>passenger_restart_dir '<%= app[:restart_dir] %>';<% end %>
|
142
142
|
<% if @options[:sticky_sessions] %>passenger_sticky_sessions on;<% end %>
|
143
|
-
<% if @options[:sticky_sessions_cookie_name] %>passenger_sticky_sessions_cookie_name '<%= sticky_sessions_cookie_name %>';<% end %>
|
143
|
+
<% if @options[:sticky_sessions_cookie_name] %>passenger_sticky_sessions_cookie_name '<%= @options[:sticky_sessions_cookie_name] %>';<% end %>
|
144
|
+
<% if @options[:vary_turbocache_by_cookie] %>passenger_vary_turbocache_by_cookie '<%= @options[:vary_turbocache_by_cookie] %>';<% end %>
|
144
145
|
<% if app[:union_station_key] %>
|
145
146
|
union_station_support on;
|
146
147
|
union_station_key <%= app[:union_station_key] %>;
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#include "TestSupport.h"
|
2
|
+
#include <cstring>
|
3
|
+
#include <Utils/DateParsing.h>
|
4
|
+
|
5
|
+
using namespace Passenger;
|
6
|
+
using namespace std;
|
7
|
+
|
8
|
+
namespace tut {
|
9
|
+
struct DateParsingTest {
|
10
|
+
struct tm tm;
|
11
|
+
int zone;
|
12
|
+
|
13
|
+
DateParsingTest() {
|
14
|
+
memset(&tm, 0, sizeof(tm));
|
15
|
+
zone = 0;
|
16
|
+
}
|
17
|
+
|
18
|
+
void parse(const char *datestr) {
|
19
|
+
const char *end = datestr + strlen(datestr);
|
20
|
+
ensure("Parsing succeeds", parseImfFixdate(datestr, end, tm, zone));
|
21
|
+
}
|
22
|
+
};
|
23
|
+
|
24
|
+
DEFINE_TEST_GROUP(DateParsingTest);
|
25
|
+
|
26
|
+
/***** Valid dates *****/
|
27
|
+
|
28
|
+
TEST_METHOD(1) {
|
29
|
+
parse("Thu, 08 Jan 2015 16:20:46 GMT");
|
30
|
+
ensure_equals(tm.tm_year, 2015 - 1900);
|
31
|
+
ensure_equals(tm.tm_mon, 0);
|
32
|
+
ensure_equals(tm.tm_mday, 8);
|
33
|
+
ensure_equals(tm.tm_hour, 16);
|
34
|
+
ensure_equals(tm.tm_min, 20);
|
35
|
+
ensure_equals(tm.tm_sec, 46);
|
36
|
+
ensure_equals(zone, 0);
|
37
|
+
ensure_equals(parsedDateToTimestamp(tm, zone), 1420734046);
|
38
|
+
}
|
39
|
+
|
40
|
+
TEST_METHOD(2) {
|
41
|
+
parse("Thu, 01 Dec 1994 16:00:00 GMT");
|
42
|
+
ensure_equals(tm.tm_year, 1994 - 1900);
|
43
|
+
ensure_equals(tm.tm_mon, 11);
|
44
|
+
ensure_equals(tm.tm_mday, 1);
|
45
|
+
ensure_equals(tm.tm_hour, 16);
|
46
|
+
ensure_equals(tm.tm_min, 0);
|
47
|
+
ensure_equals(tm.tm_sec, 0);
|
48
|
+
ensure_equals(zone, 0);
|
49
|
+
ensure_equals(parsedDateToTimestamp(tm, zone), 786297600);
|
50
|
+
}
|
51
|
+
|
52
|
+
TEST_METHOD(3) {
|
53
|
+
parse("Sun, 06 Nov 1994 08:49:37 GMT");
|
54
|
+
ensure_equals(tm.tm_year, 1994 - 1900);
|
55
|
+
ensure_equals(tm.tm_mon, 10);
|
56
|
+
ensure_equals(tm.tm_mday, 6);
|
57
|
+
ensure_equals(tm.tm_hour, 8);
|
58
|
+
ensure_equals(tm.tm_min, 49);
|
59
|
+
ensure_equals(tm.tm_sec, 37);
|
60
|
+
ensure_equals(zone, 0);
|
61
|
+
ensure_equals(parsedDateToTimestamp(tm, zone), 784111777);
|
62
|
+
}
|
63
|
+
|
64
|
+
TEST_METHOD(4) {
|
65
|
+
parse("Thu, 08 Jan 2015 17:33:14 -0300");
|
66
|
+
ensure_equals(tm.tm_year, 2015 - 1900);
|
67
|
+
ensure_equals(tm.tm_mon, 0);
|
68
|
+
ensure_equals(tm.tm_mday, 8);
|
69
|
+
ensure_equals(tm.tm_hour, 17);
|
70
|
+
ensure_equals(tm.tm_min, 33);
|
71
|
+
ensure_equals(tm.tm_sec, 14);
|
72
|
+
ensure_equals(zone, -300);
|
73
|
+
ensure_equals(parsedDateToTimestamp(tm, zone), 1420749194);
|
74
|
+
}
|
75
|
+
}
|
@@ -0,0 +1,322 @@
|
|
1
|
+
#include "TestSupport.h"
|
2
|
+
#include <ServerKit/HttpRequest.h>
|
3
|
+
#include <MemoryKit/palloc.h>
|
4
|
+
#include <agents/HelperAgent/RequestHandler/Request.h>
|
5
|
+
#include <agents/HelperAgent/RequestHandler/AppResponse.h>
|
6
|
+
#include <agents/HelperAgent/ResponseCache.h>
|
7
|
+
|
8
|
+
using namespace Passenger;
|
9
|
+
using namespace Passenger::ServerKit;
|
10
|
+
using namespace std;
|
11
|
+
|
12
|
+
namespace tut {
|
13
|
+
typedef ResponseCache<Request> ResponseCacheType;
|
14
|
+
|
15
|
+
struct ResponseCacheTest {
|
16
|
+
ResponseCacheType responseCache;
|
17
|
+
Request req;
|
18
|
+
StaticString defaultVaryTurbocacheByCookie;
|
19
|
+
|
20
|
+
ResponseCacheTest() {
|
21
|
+
req.httpMajor = 1;
|
22
|
+
req.httpMinor = 0;
|
23
|
+
req.httpState = Request::COMPLETE;
|
24
|
+
req.bodyType = Request::RBT_NO_BODY;
|
25
|
+
req.method = HTTP_GET;
|
26
|
+
req.wantKeepAlive = false;
|
27
|
+
req.responseBegun = false;
|
28
|
+
req.client = NULL;
|
29
|
+
req.pool = psg_create_pool(PSG_DEFAULT_POOL_SIZE);
|
30
|
+
req.hooks.impl = NULL;
|
31
|
+
req.hooks.userData = NULL;
|
32
|
+
psg_lstr_init(&req.path);
|
33
|
+
psg_lstr_append(&req.path, req.pool, "/");
|
34
|
+
req.bodyAlreadyRead = 0;
|
35
|
+
req.queryStringIndex = -1;
|
36
|
+
req.bodyError = 0;
|
37
|
+
|
38
|
+
req.startedAt = 0;
|
39
|
+
req.state = Request::ANALYZING_REQUEST;
|
40
|
+
req.dechunkResponse = false;
|
41
|
+
req.requestBodyBuffering = false;
|
42
|
+
req.https = false;
|
43
|
+
req.stickySession = false;
|
44
|
+
req.halfCloseAppConnection = false;
|
45
|
+
req.sessionCheckoutTry = 0;
|
46
|
+
req.strip100ContinueHeader = false;
|
47
|
+
req.hasPragmaHeader = false;
|
48
|
+
req.host = createHostString();
|
49
|
+
req.bodyBytesBuffered = 0;
|
50
|
+
req.cacheControl = NULL;
|
51
|
+
req.varyCookie = NULL;
|
52
|
+
|
53
|
+
req.appResponse.httpMajor = 1;
|
54
|
+
req.appResponse.httpMinor = 1;
|
55
|
+
req.appResponse.httpState = AppResponse::COMPLETE;
|
56
|
+
req.appResponse.wantKeepAlive = false;
|
57
|
+
req.appResponse.oneHundredContinueSent = false;
|
58
|
+
req.appResponse.bodyType = AppResponse::RBT_NO_BODY;
|
59
|
+
req.appResponse.statusCode = 200;
|
60
|
+
req.appResponse.bodyAlreadyRead = 0;
|
61
|
+
req.appResponse.date = NULL;
|
62
|
+
req.appResponse.setCookie = NULL;
|
63
|
+
req.appResponse.cacheControl = NULL;
|
64
|
+
req.appResponse.expiresHeader = NULL;
|
65
|
+
req.appResponse.lastModifiedHeader = NULL;
|
66
|
+
req.appResponse.headerCacheBuffers = NULL;
|
67
|
+
req.appResponse.nHeaderCacheBuffers = 0;
|
68
|
+
psg_lstr_init(&req.appResponse.bodyCacheBuffer);
|
69
|
+
}
|
70
|
+
|
71
|
+
~ResponseCacheTest() {
|
72
|
+
psg_destroy_pool(req.pool);
|
73
|
+
}
|
74
|
+
|
75
|
+
LString *createHostString() {
|
76
|
+
LString *str = (LString *) psg_palloc(req.pool, sizeof(LString));
|
77
|
+
psg_lstr_init(str);
|
78
|
+
psg_lstr_append(str, req.pool, "foo.com");
|
79
|
+
return str;
|
80
|
+
}
|
81
|
+
|
82
|
+
Header *createHeader(const HashedStaticString &key, const StaticString &val) {
|
83
|
+
Header *header = (Header *) psg_palloc(req.pool, sizeof(Header));
|
84
|
+
psg_lstr_init(&header->key);
|
85
|
+
psg_lstr_init(&header->val);
|
86
|
+
psg_lstr_append(&header->key, req.pool, key.data(), key.size());
|
87
|
+
psg_lstr_append(&header->val, req.pool, val.data(), val.size());
|
88
|
+
header->hash = key.hash();
|
89
|
+
return header;
|
90
|
+
}
|
91
|
+
|
92
|
+
void initCacheableResponse() {
|
93
|
+
req.appResponse.headers.insert(createHeader(
|
94
|
+
"cache-control", "public,max-age=99999"),
|
95
|
+
req.pool);
|
96
|
+
}
|
97
|
+
|
98
|
+
void initUncacheableResponse() {
|
99
|
+
req.appResponse.headers.insert(createHeader(
|
100
|
+
"cache-control", "private"),
|
101
|
+
req.pool);
|
102
|
+
}
|
103
|
+
};
|
104
|
+
|
105
|
+
DEFINE_TEST_GROUP(ResponseCacheTest);
|
106
|
+
|
107
|
+
|
108
|
+
/***** Preparation *****/
|
109
|
+
|
110
|
+
TEST_METHOD(1) {
|
111
|
+
set_test_name("It works on a GET request with no body");
|
112
|
+
ensure(responseCache.prepareRequest(this, &req));
|
113
|
+
}
|
114
|
+
|
115
|
+
TEST_METHOD(2) {
|
116
|
+
set_test_name("It fails on upgraded requests");
|
117
|
+
req.bodyType = Request::RBT_UPGRADE;
|
118
|
+
ensure(!responseCache.prepareRequest(this, &req));
|
119
|
+
ensure_equals(req.cacheKey.size(), 0u);
|
120
|
+
}
|
121
|
+
|
122
|
+
TEST_METHOD(3) {
|
123
|
+
set_test_name("It fails on requests without a host name");
|
124
|
+
req.host = NULL;
|
125
|
+
ensure(!responseCache.prepareRequest(this, &req));
|
126
|
+
ensure_equals(req.cacheKey.size(), 0u);
|
127
|
+
}
|
128
|
+
|
129
|
+
TEST_METHOD(4) {
|
130
|
+
set_test_name("It fails if the path is too long");
|
131
|
+
psg_lstr_append(&req.path, req.pool, "fooooooooooooooooooooooooooo"
|
132
|
+
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
133
|
+
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
134
|
+
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
135
|
+
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
136
|
+
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
137
|
+
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
|
138
|
+
"ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo");
|
139
|
+
ensure(!responseCache.prepareRequest(this, &req));
|
140
|
+
ensure_equals(req.cacheKey.size(), 0u);
|
141
|
+
}
|
142
|
+
|
143
|
+
TEST_METHOD(7) {
|
144
|
+
set_test_name("It generates a cache key on success");
|
145
|
+
ensure(responseCache.prepareRequest(this, &req));
|
146
|
+
ensure(req.cacheKey.size() > 0);
|
147
|
+
}
|
148
|
+
|
149
|
+
|
150
|
+
/***** Checking whether request should be fetched from cache *****/
|
151
|
+
|
152
|
+
TEST_METHOD(15) {
|
153
|
+
set_test_name("It succeeds on GET requests");
|
154
|
+
ensure(responseCache.prepareRequest(this, &req));
|
155
|
+
ensure(responseCache.requestAllowsFetching(&req));
|
156
|
+
}
|
157
|
+
|
158
|
+
TEST_METHOD(16) {
|
159
|
+
set_test_name("It succeeds on HEAD requests");
|
160
|
+
req.method = HTTP_HEAD;
|
161
|
+
ensure(responseCache.prepareRequest(this, &req));
|
162
|
+
ensure(responseCache.requestAllowsFetching(&req));
|
163
|
+
}
|
164
|
+
|
165
|
+
TEST_METHOD(17) {
|
166
|
+
set_test_name("It fails on POST requests");
|
167
|
+
req.method = HTTP_POST;
|
168
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
169
|
+
ensure("(2)", !responseCache.requestAllowsFetching(&req));
|
170
|
+
}
|
171
|
+
|
172
|
+
TEST_METHOD(18) {
|
173
|
+
set_test_name("It fails on non-GET and non-HEAD requests");
|
174
|
+
req.method = HTTP_OPTIONS;
|
175
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
176
|
+
ensure("(2)", !responseCache.requestAllowsFetching(&req));
|
177
|
+
}
|
178
|
+
|
179
|
+
TEST_METHOD(19) {
|
180
|
+
set_test_name("It fails if the request has a Cache-Control header");
|
181
|
+
req.headers.insert(createHeader(
|
182
|
+
"cache-control", "xyz"),
|
183
|
+
req.pool);
|
184
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
185
|
+
ensure("(2)", !responseCache.requestAllowsFetching(&req));
|
186
|
+
}
|
187
|
+
|
188
|
+
TEST_METHOD(20) {
|
189
|
+
set_test_name("It fails if the request has a Pragma header");
|
190
|
+
req.headers.insert(createHeader(
|
191
|
+
"pragma", "xyz"),
|
192
|
+
req.pool);
|
193
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
194
|
+
ensure("(2)", !responseCache.requestAllowsFetching(&req));
|
195
|
+
}
|
196
|
+
|
197
|
+
|
198
|
+
/***** Checking whether request should be stored to cache *****/
|
199
|
+
|
200
|
+
TEST_METHOD(30) {
|
201
|
+
set_test_name("It fails on HEAD requests");
|
202
|
+
initCacheableResponse();
|
203
|
+
req.method = HTTP_HEAD;
|
204
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
205
|
+
ensure("(2)", !responseCache.requestAllowsStoring(&req));
|
206
|
+
}
|
207
|
+
|
208
|
+
TEST_METHOD(31) {
|
209
|
+
set_test_name("It fails on all non-GET requests");
|
210
|
+
initCacheableResponse();
|
211
|
+
req.method = HTTP_POST;
|
212
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
213
|
+
ensure("(2)", !responseCache.requestAllowsStoring(&req));
|
214
|
+
}
|
215
|
+
|
216
|
+
TEST_METHOD(32) {
|
217
|
+
set_test_name("It fails if the request's Cache-Control header contains no-store");
|
218
|
+
initCacheableResponse();
|
219
|
+
req.headers.insert(createHeader(
|
220
|
+
"cache-control", "no-store"),
|
221
|
+
req.pool);
|
222
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
223
|
+
ensure("(2)", !responseCache.requestAllowsStoring(&req));
|
224
|
+
}
|
225
|
+
|
226
|
+
TEST_METHOD(33) {
|
227
|
+
set_test_name("It fails if the request is not default cacheable");
|
228
|
+
req.appResponse.statusCode = 205;
|
229
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
230
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
231
|
+
ensure("(3)", !responseCache.prepareRequestForStoring(&req));
|
232
|
+
}
|
233
|
+
|
234
|
+
TEST_METHOD(34) {
|
235
|
+
set_test_name("It fails if the request is default cacheable, but the response has "
|
236
|
+
"no Cache-Control and no Expires header that allow caching");
|
237
|
+
ensure_equals(req.appResponse.statusCode, 200);
|
238
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
239
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
240
|
+
ensure("(3)", !responseCache.prepareRequestForStoring(&req));
|
241
|
+
}
|
242
|
+
|
243
|
+
TEST_METHOD(35) {
|
244
|
+
set_test_name("It succeeds if the response contains a Cache-Control header with public directive");
|
245
|
+
req.appResponse.headers.insert(createHeader(
|
246
|
+
"cache-control", "public"),
|
247
|
+
req.pool);
|
248
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
249
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
250
|
+
ensure("(3)", responseCache.prepareRequestForStoring(&req));
|
251
|
+
}
|
252
|
+
|
253
|
+
TEST_METHOD(36) {
|
254
|
+
set_test_name("It succeeds if the response contains a Cache-Control header with max-age directive");
|
255
|
+
req.appResponse.headers.insert(createHeader(
|
256
|
+
"cache-control", "max-age=999"),
|
257
|
+
req.pool);
|
258
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
259
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
260
|
+
ensure("(3)", responseCache.prepareRequestForStoring(&req));
|
261
|
+
}
|
262
|
+
|
263
|
+
TEST_METHOD(37) {
|
264
|
+
set_test_name("It succeeds if the response contains an Expires header");
|
265
|
+
req.appResponse.headers.insert(createHeader(
|
266
|
+
"expires", "Tue, 01 Jan 2030 00:00:00 GMT"),
|
267
|
+
req.pool);
|
268
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
269
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
270
|
+
ensure("(3)", responseCache.prepareRequestForStoring(&req));
|
271
|
+
}
|
272
|
+
|
273
|
+
TEST_METHOD(38) {
|
274
|
+
set_test_name("It fails if the response's Cache-Control header contains no-store");
|
275
|
+
req.appResponse.headers.insert(createHeader(
|
276
|
+
"cache-control", "no-store"),
|
277
|
+
req.pool);
|
278
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
279
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
280
|
+
ensure("(3)", !responseCache.prepareRequestForStoring(&req));
|
281
|
+
}
|
282
|
+
|
283
|
+
TEST_METHOD(45) {
|
284
|
+
set_test_name("It fails if the response's Cache-Control header contains private");
|
285
|
+
req.appResponse.headers.insert(createHeader(
|
286
|
+
"cache-control", "private"),
|
287
|
+
req.pool);
|
288
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
289
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
290
|
+
ensure("(3)", !responseCache.prepareRequestForStoring(&req));
|
291
|
+
}
|
292
|
+
|
293
|
+
TEST_METHOD(46) {
|
294
|
+
set_test_name("It fails if the request has a Authorization header");
|
295
|
+
req.headers.insert(createHeader(
|
296
|
+
"authorization", "foo"),
|
297
|
+
req.pool);
|
298
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
299
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
300
|
+
ensure("(3)", !responseCache.prepareRequestForStoring(&req));
|
301
|
+
}
|
302
|
+
|
303
|
+
TEST_METHOD(47) {
|
304
|
+
set_test_name("It fails if the response has a Vary header");
|
305
|
+
req.appResponse.headers.insert(createHeader(
|
306
|
+
"vary", "foo"),
|
307
|
+
req.pool);
|
308
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
309
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
310
|
+
ensure("(3)", !responseCache.prepareRequestForStoring(&req));
|
311
|
+
}
|
312
|
+
|
313
|
+
TEST_METHOD(48) {
|
314
|
+
set_test_name("It fails if the response has a WWW-Authenticate header");
|
315
|
+
req.appResponse.headers.insert(createHeader(
|
316
|
+
"www-authenticate", "foo"),
|
317
|
+
req.pool);
|
318
|
+
ensure("(1)", responseCache.prepareRequest(this, &req));
|
319
|
+
ensure("(2)", responseCache.requestAllowsStoring(&req));
|
320
|
+
ensure("(3)", !responseCache.prepareRequestForStoring(&req));
|
321
|
+
}
|
322
|
+
}
|