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.

Files changed (73) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +30 -0
  5. data/CONTRIBUTORS +2 -0
  6. data/Gemfile.lock +1 -1
  7. data/bin/passenger-status +13 -15
  8. data/build/cxx_tests.rb +14 -1
  9. data/build/preprocessor.rb +4 -2
  10. data/debian.template/control.template +2 -2
  11. data/doc/Security of user switching support.txt +2 -2
  12. data/doc/Users guide Apache.idmap.txt +6 -4
  13. data/doc/Users guide Apache.txt +20 -1
  14. data/doc/Users guide Nginx.idmap.txt +5 -3
  15. data/doc/Users guide Nginx.txt +22 -2
  16. data/ext/apache2/Configuration.cpp +6 -0
  17. data/ext/apache2/Configuration.hpp +4 -1
  18. data/ext/apache2/Hooks.cpp +1 -0
  19. data/ext/common/Constants.h +4 -2
  20. data/ext/common/Constants.h.erb +1 -1
  21. data/ext/common/DataStructures/LString.h +10 -0
  22. data/ext/common/ServerKit/Channel.h +1 -1
  23. data/ext/common/ServerKit/Context.h +2 -21
  24. data/ext/common/ServerKit/CookieUtils.h +246 -0
  25. data/ext/common/ServerKit/FdSourceChannel.h +10 -0
  26. data/ext/common/ServerKit/FileBufferedChannel.h +173 -17
  27. data/ext/common/ServerKit/FileBufferedFdSinkChannel.h +33 -1
  28. data/ext/common/ServerKit/HeaderTable.h +3 -1
  29. data/ext/common/ServerKit/HttpServer.h +36 -8
  30. data/ext/common/ServerKit/Server.h +1 -0
  31. data/ext/common/Utils.cpp +2 -1
  32. data/ext/common/Utils/DateParsing.h +15 -2
  33. data/ext/common/Utils/JsonUtils.h +39 -1
  34. data/ext/common/agents/HelperAgent/Main.cpp +4 -2
  35. data/ext/common/agents/HelperAgent/OptionParser.h +14 -2
  36. data/ext/common/agents/HelperAgent/RequestHandler.h +22 -8
  37. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +92 -11
  38. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +3 -1
  39. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +9 -5
  40. data/ext/common/agents/HelperAgent/RequestHandler/Request.h +1 -0
  41. data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +27 -13
  42. data/ext/common/agents/HelperAgent/ResponseCache.h +91 -34
  43. data/ext/common/agents/LoggingAgent/AdminServer.h +21 -1
  44. data/ext/nginx/CacheLocationConfig.c +20 -0
  45. data/ext/nginx/Configuration.c +130 -24
  46. data/ext/nginx/Configuration.h +2 -1
  47. data/ext/nginx/ConfigurationCommands.c +10 -0
  48. data/ext/nginx/ConfigurationFields.h +2 -0
  49. data/ext/nginx/ContentHandler.c +1 -6
  50. data/ext/nginx/CreateLocationConfig.c +5 -0
  51. data/ext/nginx/MergeLocationConfig.c +6 -0
  52. data/ext/nginx/StaticContentHandler.c +3 -9
  53. data/ext/nginx/ngx_http_passenger_module.c +2 -1
  54. data/ext/ruby/extconf.rb +5 -4
  55. data/lib/phusion_passenger.rb +2 -2
  56. data/lib/phusion_passenger/constants.rb +2 -1
  57. data/lib/phusion_passenger/nginx/config_options.rb +5 -1
  58. data/lib/phusion_passenger/rack/thread_handler_extension.rb +3 -1
  59. data/lib/phusion_passenger/ruby_core_enhancements.rb +3 -4
  60. data/lib/phusion_passenger/standalone/start_command.rb +5 -1
  61. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +10 -3
  62. data/resources/templates/standalone/config.erb +2 -1
  63. data/test/cxx/DateParsingTest.cpp +75 -0
  64. data/test/cxx/ResponseCacheTest.cpp +322 -0
  65. data/test/cxx/ServerKit/CookieUtilsTest.cpp +274 -0
  66. data/test/cxx/ServerKit/HttpServerTest.cpp +77 -0
  67. data/test/stub/rails3.0/Gemfile.lock +2 -2
  68. data/test/stub/rails3.1/Gemfile.lock +2 -2
  69. data/test/stub/rails3.2/Gemfile.lock +2 -2
  70. data/test/stub/rails4.0/Gemfile.lock +2 -2
  71. data/test/stub/rails4.1/Gemfile.lock +2 -2
  72. metadata +6 -2
  73. 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-2014 Phusion
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);
@@ -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
- $LIBS = ""
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
+
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  # Phusion Passenger - https://www.phusionpassenger.com/
3
- # Copyright (c) 2010-2014 Phusion
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.beta2'
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-2014 Phusion
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-2014 Phusion
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-2014 Phusion
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-2014 Phusion
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.ecape @options[:user]}"
83
+ command << " --default-user #{Shellwords.escape @options[:user]}"
84
84
  else
85
85
  user = Etc.getpwuid(Process.uid).name
86
- group = Etc.getgrgid(Process.gid).name
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
+ }