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,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2011-
|
3
|
+
* Copyright (c) 2011-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -68,6 +68,7 @@ onRequestObjectCreated(Client *client, Request *req) {
|
|
68
68
|
virtual void deinitializeClient(Client *client) {
|
69
69
|
ParentClass::deinitializeClient(client);
|
70
70
|
client->output.setBuffersFlushedCallback(NULL);
|
71
|
+
client->output.setDataFlushedCallback(getClientOutputDataFlushedCallback());
|
71
72
|
}
|
72
73
|
|
73
74
|
virtual void reinitializeRequest(Client *client, Request *req) {
|
@@ -90,6 +91,7 @@ virtual void reinitializeRequest(Client *client, Request *req) {
|
|
90
91
|
req->bodyBytesBuffered = 0;
|
91
92
|
req->cacheKey = HashedStaticString();
|
92
93
|
req->cacheControl = NULL;
|
94
|
+
req->varyCookie = NULL;
|
93
95
|
|
94
96
|
#ifdef DEBUG_RH_EVENT_LOOP_BLOCKING
|
95
97
|
req->timedAppPoolGet = false;
|
@@ -137,25 +137,29 @@ initializeFlags(Client *client, Request *req, RequestAnalysis &analysis) {
|
|
137
137
|
|
138
138
|
bool
|
139
139
|
respondFromTurboCache(Client *client, Request *req) {
|
140
|
-
if (!turboCaching.isEnabled() || !turboCaching.responseCache.prepareRequest(req)) {
|
140
|
+
if (!turboCaching.isEnabled() || !turboCaching.responseCache.prepareRequest(this, req)) {
|
141
141
|
return false;
|
142
142
|
}
|
143
143
|
|
144
|
-
SKC_TRACE(client, 2, "Turbocaching: trying to reply from cache"
|
144
|
+
SKC_TRACE(client, 2, "Turbocaching: trying to reply from cache (key \"" <<
|
145
|
+
cEscapeString(req->cacheKey) << "\")");
|
145
146
|
SKC_TRACE(client, 2, "Turbocache entries:\n" << turboCaching.responseCache.inspect());
|
146
147
|
|
147
148
|
if (turboCaching.responseCache.requestAllowsFetching(req)) {
|
148
149
|
ResponseCache<Request>::Entry entry(turboCaching.responseCache.fetch(req,
|
149
150
|
ev_now(getLoop())));
|
150
151
|
if (entry.valid()) {
|
151
|
-
SKC_TRACE(client, 2, "Turbocaching: cache hit (key " <<
|
152
|
+
SKC_TRACE(client, 2, "Turbocaching: cache hit (key \"" <<
|
153
|
+
cEscapeString(req->cacheKey) << "\")");
|
152
154
|
turboCaching.writeResponse(this, client, req, entry);
|
153
155
|
if (!req->ended()) {
|
154
156
|
endRequest(&client, &req);
|
155
157
|
}
|
156
158
|
return true;
|
157
159
|
} else {
|
158
|
-
SKC_TRACE(client, 2, "Turbocaching: cache miss
|
160
|
+
SKC_TRACE(client, 2, "Turbocaching: cache miss: " <<
|
161
|
+
entry.getCacheMissReasonString() <<
|
162
|
+
" (key \"" << cEscapeString(req->cacheKey) << "\")");
|
159
163
|
return false;
|
160
164
|
}
|
161
165
|
} else {
|
@@ -428,7 +432,7 @@ getStickySessionCookieName(Request *req) {
|
|
428
432
|
const LString *value = req->headers.lookup(PASSENGER_STICKY_SESSIONS_COOKIE_NAME);
|
429
433
|
if (value == NULL || value->size == 0) {
|
430
434
|
return psg_lstr_create(req->pool,
|
431
|
-
|
435
|
+
defaultStickySessionsCookieName);
|
432
436
|
} else {
|
433
437
|
return value;
|
434
438
|
}
|
@@ -87,8 +87,8 @@ struct SessionProtocolWorkingState {
|
|
87
87
|
const LString *remoteAddr;
|
88
88
|
const LString *remotePort;
|
89
89
|
const LString *remoteUser;
|
90
|
-
const LString *contentLength;
|
91
90
|
const LString *contentType;
|
91
|
+
const LString *contentLength;
|
92
92
|
bool hasBaseURI;
|
93
93
|
};
|
94
94
|
|
@@ -177,8 +177,12 @@ determineHeaderSizeForSessionProtocol(Request *req,
|
|
177
177
|
state.remoteAddr = req->secureHeaders.lookup(REMOTE_ADDR);
|
178
178
|
state.remotePort = req->secureHeaders.lookup(REMOTE_PORT);
|
179
179
|
state.remoteUser = req->secureHeaders.lookup(REMOTE_USER);
|
180
|
-
state.contentLength = req->headers.lookup(HTTP_CONTENT_LENGTH);
|
181
180
|
state.contentType = req->headers.lookup(HTTP_CONTENT_TYPE);
|
181
|
+
if (req->hasBody()) {
|
182
|
+
state.contentLength = req->headers.lookup(HTTP_CONTENT_LENGTH);
|
183
|
+
} else {
|
184
|
+
state.contentLength = NULL;
|
185
|
+
}
|
182
186
|
|
183
187
|
dataSize += sizeof("REQUEST_URI");
|
184
188
|
dataSize += req->path.size + 1;
|
@@ -246,16 +250,16 @@ determineHeaderSizeForSessionProtocol(Request *req,
|
|
246
250
|
dataSize += state.remoteUser->size + 1;
|
247
251
|
}
|
248
252
|
|
249
|
-
if (state.contentLength != NULL) {
|
250
|
-
dataSize += sizeof("CONTENT_LENGTH");
|
251
|
-
dataSize += state.contentLength->size + 1;
|
252
|
-
}
|
253
|
-
|
254
253
|
if (state.contentType != NULL) {
|
255
254
|
dataSize += sizeof("CONTENT_TYPE");
|
256
255
|
dataSize += state.contentType->size + 1;
|
257
256
|
}
|
258
257
|
|
258
|
+
if (state.contentLength != NULL) {
|
259
|
+
dataSize += sizeof("CONTENT_LENGTH");
|
260
|
+
dataSize += state.contentLength->size + 1;
|
261
|
+
}
|
262
|
+
|
259
263
|
dataSize += sizeof("PASSENGER_CONNECT_PASSWORD");
|
260
264
|
dataSize += req->session->getGroupSecret().size() + 1;
|
261
265
|
|
@@ -269,6 +273,11 @@ determineHeaderSizeForSessionProtocol(Request *req,
|
|
269
273
|
dataSize += req->options.transaction->getTxnId().size() + 1;
|
270
274
|
}
|
271
275
|
|
276
|
+
if (req->upgraded()) {
|
277
|
+
dataSize += sizeof("HTTP_CONNECTION");
|
278
|
+
dataSize += sizeof("upgrade");
|
279
|
+
}
|
280
|
+
|
272
281
|
ServerKit::HeaderTable::Iterator it(req->headers);
|
273
282
|
while (*it != NULL) {
|
274
283
|
dataSize += sizeof("HTTP_") - 1 + it->header->key.size + 1;
|
@@ -349,18 +358,18 @@ constructHeaderForSessionProtocol(Request *req, char * restrict buffer, unsigned
|
|
349
358
|
pos = appendData(pos, end, "", 1);
|
350
359
|
}
|
351
360
|
|
352
|
-
if (state.contentLength != NULL) {
|
353
|
-
pos = appendData(pos, end, P_STATIC_STRING_WITH_NULL("CONTENT_LENGTH"));
|
354
|
-
pos = appendData(pos, end, state.contentLength);
|
355
|
-
pos = appendData(pos, end, "", 1);
|
356
|
-
}
|
357
|
-
|
358
361
|
if (state.contentType != NULL) {
|
359
362
|
pos = appendData(pos, end, P_STATIC_STRING_WITH_NULL("CONTENT_TYPE"));
|
360
363
|
pos = appendData(pos, end, state.contentType);
|
361
364
|
pos = appendData(pos, end, "", 1);
|
362
365
|
}
|
363
366
|
|
367
|
+
if (state.contentLength != NULL) {
|
368
|
+
pos = appendData(pos, end, P_STATIC_STRING_WITH_NULL("CONTENT_LENGTH"));
|
369
|
+
pos = appendData(pos, end, state.contentLength);
|
370
|
+
pos = appendData(pos, end, "", 1);
|
371
|
+
}
|
372
|
+
|
364
373
|
pos = appendData(pos, end, P_STATIC_STRING_WITH_NULL("PASSENGER_CONNECT_PASSWORD"));
|
365
374
|
pos = appendData(pos, end, req->session->getGroupSecret());
|
366
375
|
pos = appendData(pos, end, "", 1);
|
@@ -376,6 +385,11 @@ constructHeaderForSessionProtocol(Request *req, char * restrict buffer, unsigned
|
|
376
385
|
pos = appendData(pos, end, "", 1);
|
377
386
|
}
|
378
387
|
|
388
|
+
if (req->upgraded()) {
|
389
|
+
pos = appendData(pos, end, P_STATIC_STRING_WITH_NULL("HTTP_CONNECTION"));
|
390
|
+
pos = appendData(pos, end, P_STATIC_STRING_WITH_NULL("upgrade"));
|
391
|
+
}
|
392
|
+
|
379
393
|
ServerKit::HeaderTable::Iterator it(req->headers);
|
380
394
|
while (*it != NULL) {
|
381
395
|
if ((it->header->hash == HTTP_CONTENT_LENGTH.hash()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* Phusion Passenger - https://www.phusionpassenger.com/
|
3
|
-
* Copyright (c) 2014 Phusion
|
3
|
+
* Copyright (c) 2014-2015 Phusion
|
4
4
|
*
|
5
5
|
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
|
6
6
|
*
|
@@ -31,13 +31,18 @@
|
|
31
31
|
#include <cstring>
|
32
32
|
#include <DataStructures/HashedStaticString.h>
|
33
33
|
#include <ServerKit/http_parser.h>
|
34
|
+
#include <ServerKit/CookieUtils.h>
|
34
35
|
#include <StaticString.h>
|
35
36
|
#include <Utils/DateParsing.h>
|
36
37
|
#include <Utils/StrIntUtils.h>
|
37
38
|
|
38
39
|
namespace Passenger {
|
39
40
|
|
40
|
-
|
41
|
+
/**
|
42
|
+
* Relevant RFCs:
|
43
|
+
* https://tools.ietf.org/html/rfc7234 HTTP 1.1 Caching
|
44
|
+
* https://tools.ietf.org/html/rfc2109 HTTP State Management Mechanism
|
45
|
+
*/
|
41
46
|
template<typename Request>
|
42
47
|
class ResponseCache {
|
43
48
|
public:
|
@@ -73,6 +78,10 @@ public:
|
|
73
78
|
unsigned int index;
|
74
79
|
Header *header;
|
75
80
|
Body *body;
|
81
|
+
enum {
|
82
|
+
NOT_FOUND,
|
83
|
+
NOT_FRESH
|
84
|
+
} cacheMissReason;
|
76
85
|
|
77
86
|
Entry()
|
78
87
|
: index(0),
|
@@ -90,29 +99,48 @@ public:
|
|
90
99
|
bool valid() const {
|
91
100
|
return header != NULL;
|
92
101
|
}
|
102
|
+
|
103
|
+
const char *getCacheMissReasonString() const {
|
104
|
+
switch (cacheMissReason) {
|
105
|
+
case NOT_FOUND:
|
106
|
+
return "NOT_FOUND";
|
107
|
+
case NOT_FRESH:
|
108
|
+
return "NOT_FRESH";
|
109
|
+
default:
|
110
|
+
return "UNKNOWN";
|
111
|
+
}
|
112
|
+
}
|
93
113
|
};
|
94
114
|
|
95
115
|
private:
|
96
116
|
HashedStaticString HOST;
|
97
117
|
HashedStaticString CACHE_CONTROL;
|
98
118
|
HashedStaticString PRAGMA_CONST;
|
119
|
+
HashedStaticString AUTHORIZATION;
|
99
120
|
HashedStaticString VARY;
|
121
|
+
HashedStaticString WWW_AUTHENTICATE;
|
100
122
|
HashedStaticString EXPIRES;
|
101
123
|
HashedStaticString LAST_MODIFIED;
|
102
124
|
HashedStaticString LOCATION;
|
103
125
|
HashedStaticString CONTENT_LOCATION;
|
126
|
+
HashedStaticString COOKIE;
|
127
|
+
HashedStaticString PASSENGER_VARY_TURBOCACHE_BY_COOKIE;
|
104
128
|
|
105
129
|
unsigned int fetches, hits, stores, storeSuccesses;
|
106
130
|
|
107
131
|
Header headers[MAX_ENTRIES];
|
108
132
|
Body bodies[MAX_ENTRIES];
|
109
133
|
|
110
|
-
unsigned int calculateKeyLength(const LString * restrict host,
|
134
|
+
unsigned int calculateKeyLength(const LString * restrict host,
|
135
|
+
const LString * restrict varyCookie,
|
136
|
+
const StaticString &path)
|
137
|
+
{
|
111
138
|
unsigned int size =
|
112
139
|
1 // protocol flag
|
113
140
|
+ ((host != NULL) ? host->size : 0)
|
114
|
-
+ 1 // '
|
115
|
-
+ path.size()
|
141
|
+
+ 1 // '\n'
|
142
|
+
+ path.size()
|
143
|
+
+ ((varyCookie != NULL) ? (varyCookie->size + 1) : 0);
|
116
144
|
if (size > MAX_KEY_LENGTH) {
|
117
145
|
return 0;
|
118
146
|
} else {
|
@@ -121,7 +149,9 @@ private:
|
|
121
149
|
}
|
122
150
|
|
123
151
|
void generateKey(bool https, const StaticString &path,
|
124
|
-
const LString * restrict host,
|
152
|
+
const LString * restrict host,
|
153
|
+
const LString * restrict varyCookie,
|
154
|
+
char * restrict output,
|
125
155
|
unsigned int size)
|
126
156
|
{
|
127
157
|
char *pos = output;
|
@@ -142,8 +172,17 @@ private:
|
|
142
172
|
}
|
143
173
|
}
|
144
174
|
|
145
|
-
pos = appendData(pos, end, "
|
175
|
+
pos = appendData(pos, end, "\n", 1);
|
146
176
|
pos = appendData(pos, end, path);
|
177
|
+
|
178
|
+
if (varyCookie != NULL) {
|
179
|
+
pos = appendData(pos, end, "\n", 1);
|
180
|
+
part = varyCookie->start;
|
181
|
+
while (part != NULL) {
|
182
|
+
pos = appendData(pos, end, part->data, part->size);
|
183
|
+
part = part->next;
|
184
|
+
}
|
185
|
+
}
|
147
186
|
}
|
148
187
|
|
149
188
|
bool statusCodeIsCacheableByDefault(unsigned int code) const {
|
@@ -194,10 +233,6 @@ private:
|
|
194
233
|
headers[index].valid = false;
|
195
234
|
}
|
196
235
|
|
197
|
-
time_t parsedDateToTimestamp(struct tm &tm, int zone) const {
|
198
|
-
return mktime(&tm) - zone / 100 * 60 * 60 - zone % 100 * 60;
|
199
|
-
}
|
200
|
-
|
201
236
|
time_t parseDate(psg_pool_t *pool, const LString *date, ev_tstamp now) const {
|
202
237
|
if (date == NULL) {
|
203
238
|
return (time_t) now;
|
@@ -345,13 +380,13 @@ private:
|
|
345
380
|
https = req->https;
|
346
381
|
}
|
347
382
|
|
348
|
-
unsigned int keySize = calculateKeyLength(req->host, path);
|
383
|
+
unsigned int keySize = calculateKeyLength(req->host, req->varyCookie, path);
|
349
384
|
if (keySize == 0) {
|
350
385
|
return;
|
351
386
|
}
|
352
387
|
|
353
388
|
char *key = (char *) psg_pnalloc(req->pool, keySize);
|
354
|
-
generateKey(https, path, req->host, key, keySize);
|
389
|
+
generateKey(https, path, req->host, req->varyCookie, key, keySize);
|
355
390
|
|
356
391
|
Entry entry(lookup(StaticString(key, keySize)));
|
357
392
|
if (entry.valid()) {
|
@@ -363,11 +398,15 @@ public:
|
|
363
398
|
ResponseCache()
|
364
399
|
: CACHE_CONTROL("cache-control"),
|
365
400
|
PRAGMA_CONST("pragma"),
|
401
|
+
AUTHORIZATION("authorization"),
|
366
402
|
VARY("vary"),
|
403
|
+
WWW_AUTHENTICATE("www-authenticate"),
|
367
404
|
EXPIRES("expires"),
|
368
405
|
LAST_MODIFIED("last-modified"),
|
369
406
|
LOCATION("location"),
|
370
407
|
CONTENT_LOCATION("content-location"),
|
408
|
+
COOKIE("cookie"),
|
409
|
+
PASSENGER_VARY_TURBOCACHE_BY_COOKIE("!~PASSENGER_VARY_TURBOCACHE_COOKIE"),
|
371
410
|
fetches(0),
|
372
411
|
hits(0),
|
373
412
|
stores(0),
|
@@ -430,12 +469,29 @@ public:
|
|
430
469
|
*
|
431
470
|
* @post result == !req->cacheKey.empty()
|
432
471
|
*/
|
433
|
-
|
472
|
+
template<typename RequestHandler>
|
473
|
+
bool prepareRequest(RequestHandler *requestHandler, Request *req) {
|
434
474
|
if (req->upgraded() || req->host == NULL) {
|
435
475
|
return false;
|
436
476
|
}
|
437
477
|
|
478
|
+
LString *varyCookieName = req->secureHeaders.lookup(PASSENGER_VARY_TURBOCACHE_BY_COOKIE);
|
479
|
+
if (varyCookieName == NULL && !requestHandler->defaultVaryTurbocacheByCookie.empty()) {
|
480
|
+
varyCookieName = (LString *) psg_palloc(req->pool, sizeof(LString));
|
481
|
+
psg_lstr_init(varyCookieName);
|
482
|
+
psg_lstr_append(varyCookieName, req->pool,
|
483
|
+
requestHandler->defaultVaryTurbocacheByCookie.data(),
|
484
|
+
requestHandler->defaultVaryTurbocacheByCookie.size());
|
485
|
+
}
|
486
|
+
if (varyCookieName != NULL) {
|
487
|
+
LString *cookieHeader = req->headers.lookup(COOKIE);
|
488
|
+
if (cookieHeader != NULL) {
|
489
|
+
req->varyCookie = ServerKit::findCookie(req->pool, cookieHeader, varyCookieName);
|
490
|
+
}
|
491
|
+
}
|
492
|
+
|
438
493
|
unsigned int size = calculateKeyLength(req->host,
|
494
|
+
req->varyCookie,
|
439
495
|
StaticString(req->path.start->data, req->path.size));
|
440
496
|
if (size == 0) {
|
441
497
|
req->cacheKey = HashedStaticString();
|
@@ -443,7 +499,7 @@ public:
|
|
443
499
|
}
|
444
500
|
|
445
501
|
req->cacheControl = req->headers.lookup(CACHE_CONTROL);
|
446
|
-
if (req->cacheControl
|
502
|
+
if (req->cacheControl == NULL) {
|
447
503
|
// hasPragmaHeader is only used by requestAllowsFetching(),
|
448
504
|
// so if there is no Cache-Control header then it's not
|
449
505
|
// necessary to check for the Pragma header.
|
@@ -452,7 +508,7 @@ public:
|
|
452
508
|
|
453
509
|
char *key = (char *) psg_pnalloc(req->pool, size);
|
454
510
|
generateKey(req->https, StaticString(req->path.start->data, req->path.size),
|
455
|
-
req->host, key, size);
|
511
|
+
req->host, req->varyCookie, key, size);
|
456
512
|
req->cacheKey = HashedStaticString(key, size);
|
457
513
|
return true;
|
458
514
|
}
|
@@ -481,9 +537,12 @@ public:
|
|
481
537
|
return entry;
|
482
538
|
} else {
|
483
539
|
erase(entry.index);
|
484
|
-
|
540
|
+
Entry result;
|
541
|
+
result.cacheMissReason = Entry::NOT_FRESH;
|
542
|
+
return result;
|
485
543
|
}
|
486
544
|
} else {
|
545
|
+
entry.cacheMissReason = Entry::NOT_FOUND;
|
487
546
|
return entry;
|
488
547
|
}
|
489
548
|
}
|
@@ -492,7 +551,7 @@ public:
|
|
492
551
|
// @pre prepareRequest() returned true
|
493
552
|
OXT_FORCE_INLINE
|
494
553
|
bool requestAllowsStoring(Request *req) const {
|
495
|
-
return requestAllowsFetching(req);
|
554
|
+
return req->method != HTTP_HEAD && requestAllowsFetching(req);
|
496
555
|
}
|
497
556
|
|
498
557
|
// @pre prepareRequest() returned true
|
@@ -503,16 +562,6 @@ public:
|
|
503
562
|
|
504
563
|
ServerKit::HeaderTable &respHeaders = req->appResponse.headers;
|
505
564
|
|
506
|
-
if (req->cacheControl != NULL) {
|
507
|
-
req->cacheControl = psg_lstr_make_contiguous(req->cacheControl,
|
508
|
-
req->pool);
|
509
|
-
StaticString cacheControl = StaticString(req->cacheControl->start->data,
|
510
|
-
req->cacheControl->size);
|
511
|
-
if (cacheControl.find(P_STATIC_STRING("no-store")) != string::npos) {
|
512
|
-
return false;
|
513
|
-
}
|
514
|
-
}
|
515
|
-
|
516
565
|
req->appResponse.cacheControl = respHeaders.lookup(CACHE_CONTROL);
|
517
566
|
if (req->appResponse.cacheControl != NULL) {
|
518
567
|
req->appResponse.cacheControl = psg_lstr_make_contiguous(
|
@@ -521,12 +570,17 @@ public:
|
|
521
570
|
StaticString cacheControl = StaticString(
|
522
571
|
req->appResponse.cacheControl->start->data,
|
523
572
|
req->appResponse.cacheControl->size);
|
524
|
-
if (cacheControl.find(P_STATIC_STRING("no-store")) != string::npos
|
573
|
+
if (cacheControl.find(P_STATIC_STRING("no-store")) != string::npos
|
574
|
+
|| cacheControl.find(P_STATIC_STRING("private")) != string::npos)
|
575
|
+
{
|
525
576
|
return false;
|
526
577
|
}
|
527
578
|
}
|
528
579
|
|
529
|
-
if (
|
580
|
+
if (req->headers.lookup(AUTHORIZATION) != NULL
|
581
|
+
|| respHeaders.lookup(VARY) != NULL
|
582
|
+
|| respHeaders.lookup(WWW_AUTHENTICATE) != NULL)
|
583
|
+
{
|
530
584
|
return false;
|
531
585
|
}
|
532
586
|
|
@@ -548,7 +602,8 @@ public:
|
|
548
602
|
req->pool);
|
549
603
|
}
|
550
604
|
|
551
|
-
return
|
605
|
+
return req->appResponse.cacheControl != NULL
|
606
|
+
|| req->appResponse.expiresHeader != NULL;
|
552
607
|
}
|
553
608
|
|
554
609
|
// @pre requestAllowsStoring()
|
@@ -609,10 +664,12 @@ public:
|
|
609
664
|
string inspect() const {
|
610
665
|
stringstream stream;
|
611
666
|
for (unsigned int i = 0; i < MAX_ENTRIES; i++) {
|
667
|
+
time_t expiryDate = bodies[i].expiryDate;
|
612
668
|
stream << " #" << i << ": valid=" << headers[i].valid
|
613
|
-
<< ", hash=" << headers[i].hash
|
614
|
-
<<
|
615
|
-
<<
|
669
|
+
<< ", hash=" << headers[i].hash
|
670
|
+
<< ", expiryDate=" << expiryDate
|
671
|
+
<< ", keySize=" << headers[i].keySize << ", key=\""
|
672
|
+
<< cEscapeString(StaticString(bodies[i].key, headers[i].keySize)) << "\"\n";
|
616
673
|
}
|
617
674
|
return stream.str();
|
618
675
|
}
|