You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
8.9 KiB
194 lines
8.9 KiB
diff --git a/docs/manual/mod/mod_session.html.en b/docs/manual/mod/mod_session.html.en |
|
index 96a61e6..4ecc97d 100644 |
|
--- a/docs/manual/mod/mod_session.html.en |
|
+++ b/docs/manual/mod/mod_session.html.en |
|
@@ -69,6 +69,7 @@ |
|
<li><img alt="" src="../images/down.gif" /> <a href="#sessionheader">SessionHeader</a></li> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#sessioninclude">SessionInclude</a></li> |
|
<li><img alt="" src="../images/down.gif" /> <a href="#sessionmaxage">SessionMaxAge</a></li> |
|
+<li><img alt="" src="../images/down.gif" /> <a href="#sessionexpiryupdateinterval">SessionExpiryUpdateInterval</a></li> |
|
</ul> |
|
<h3>Topics</h3> |
|
<ul id="topics"> |
|
@@ -494,6 +495,37 @@ AuthName realm |
|
|
|
<p>Setting the maxage to zero disables session expiry.</p> |
|
|
|
+</div> |
|
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> |
|
+<div class="directive-section"><h2><a name="SessionExpiryUpdateInterval" id="sessionexpiryupdateinterval">SessionExpiryUpdateInterval</a> <a name="sessionexpiryupdateinterval" id="sessionexpiryupdateinterval">Directive</a></h2> |
|
+<table class="directive"> |
|
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Define the number of seconds a session's expiry may change without the session being updated</td></tr> |
|
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>SessionExpiryUpdateInterval <var>interval</var></code></td></tr> |
|
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>SessionExpiryUpdateInterval 0 (always update)</code></td></tr> |
|
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr> |
|
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_session</td></tr> |
|
+</table> |
|
+ <p>The <code class="directive">SessionExpiryUpdateInterval</code> directive allows |
|
+ sessions to avoid the cost associated with writing the session each request |
|
+ when only the expiry time has changed. This can be used to make a website |
|
+ more efficient or reduce load on a database when using |
|
+ <module>mod_session_dbd</module>. The session is always written if the data |
|
+ stored in the session has changed or the expiry has changed by more than the |
|
+ configured interval.</p> |
|
+ |
|
+ <p>Setting the interval to zero disables this directive, and the session |
|
+ expiry is refreshed for each request.</p> |
|
+ |
|
+ <p>This directive only has an effect when combined with <code class="directive"><a href="../mod/mod_session.html#sessionmaxage">SessionMaxAge</a></code> to enable session |
|
+ expiry. Sessions without an expiry are only written when the data stored in |
|
+ the session has changed.</p> |
|
+ |
|
+ <div class="warning"><h3>Warning</h3> |
|
+ <p>Because the session expiry may not be refreshed with each request, it's |
|
+ possible for sessions to expire up to <var>interval</var> seconds early. |
|
+ Using a small interval usually provides sufficient savings while having a |
|
+ minimal effect on expiry resolution.</p></div> |
|
+ |
|
</div> |
|
</div> |
|
<div class="bottomlang"> |
|
diff --git a/modules/session/mod_session.c b/modules/session/mod_session.c |
|
index 3e73c7a..83bf3fc 100644 |
|
--- a/modules/session/mod_session.c |
|
+++ b/modules/session/mod_session.c |
|
@@ -177,6 +177,7 @@ static apr_status_t ap_session_save(request_rec * r, session_rec * z) |
|
{ |
|
if (z) { |
|
apr_time_t now = apr_time_now(); |
|
+ apr_time_t initialExpiry = z->expiry; |
|
int rv = 0; |
|
|
|
session_dir_conf *dconf = ap_get_module_config(r->per_dir_config, |
|
@@ -202,6 +203,17 @@ static apr_status_t ap_session_save(request_rec * r, session_rec * z) |
|
z->maxage = dconf->maxage; |
|
} |
|
|
|
+ /* don't save if the only change is the expiry by a small amount */ |
|
+ if (!z->dirty && dconf->expiry_update_time |
|
+ && (z->expiry - initialExpiry < dconf->expiry_update_time)) { |
|
+ return APR_SUCCESS; |
|
+ } |
|
+ |
|
+ /* also don't save sessions that didn't change at all */ |
|
+ if (!z->dirty && !z->maxage) { |
|
+ return APR_SUCCESS; |
|
+ } |
|
+ |
|
/* encode the session */ |
|
rv = ap_run_session_encode(r, z); |
|
if (OK != rv) { |
|
@@ -544,6 +556,10 @@ static void *merge_session_dir_config(apr_pool_t * p, void *basev, void *addv) |
|
new->env_set = add->env_set || base->env_set; |
|
new->includes = apr_array_append(p, base->includes, add->includes); |
|
new->excludes = apr_array_append(p, base->excludes, add->excludes); |
|
+ new->expiry_update_time = (add->expiry_update_set == 0) |
|
+ ? base->expiry_update_time |
|
+ : add->expiry_update_time; |
|
+ new->expiry_update_set = add->expiry_update_set || base->expiry_update_set; |
|
|
|
return new; |
|
} |
|
@@ -613,6 +629,21 @@ static const char *add_session_exclude(cmd_parms * cmd, void *dconf, const char |
|
return NULL; |
|
} |
|
|
|
+static const char * |
|
+ set_session_expiry_update(cmd_parms * parms, void *dconf, const char *arg) |
|
+{ |
|
+ session_dir_conf *conf = dconf; |
|
+ |
|
+ conf->expiry_update_time = atoi(arg); |
|
+ if (conf->expiry_update_time < 0) { |
|
+ return "SessionExpiryUpdateInterval must be positive or nul"; |
|
+ } |
|
+ conf->expiry_update_time = apr_time_from_sec(conf->expiry_update_time); |
|
+ conf->expiry_update_set = 1; |
|
+ |
|
+ return NULL; |
|
+} |
|
+ |
|
|
|
static const command_rec session_cmds[] = |
|
{ |
|
@@ -628,6 +659,9 @@ static const command_rec session_cmds[] = |
|
"URL prefixes to include in the session. Defaults to all URLs"), |
|
AP_INIT_TAKE1("SessionExclude", add_session_exclude, NULL, RSRC_CONF|OR_AUTHCFG, |
|
"URL prefixes to exclude from the session. Defaults to no URLs"), |
|
+ AP_INIT_TAKE1("SessionExpiryUpdateInterval", set_session_expiry_update, NULL, RSRC_CONF|OR_AUTHCFG, |
|
+ "time interval for which a session's expiry time may change " |
|
+ "without having to be rewritten. Zero to disable"), |
|
{NULL} |
|
}; |
|
|
|
diff --git a/modules/session/mod_session.h b/modules/session/mod_session.h |
|
index a6dd5e9..bdeb532 100644 |
|
--- a/modules/session/mod_session.h |
|
+++ b/modules/session/mod_session.h |
|
@@ -115,6 +115,9 @@ typedef struct { |
|
* URLs included if empty */ |
|
apr_array_header_t *excludes; /* URL prefixes to be excluded. No |
|
* URLs excluded if empty */ |
|
+ apr_time_t expiry_update_time; /* seconds the session expiry may change and |
|
+ * not have to be rewritten */ |
|
+ int expiry_update_set; |
|
} session_dir_conf; |
|
|
|
/** |
|
diff --git a/modules/session/mod_session_cookie.c b/modules/session/mod_session_cookie.c |
|
index 6a02322..4aa75e4 100644 |
|
--- a/modules/session/mod_session_cookie.c |
|
+++ b/modules/session/mod_session_cookie.c |
|
@@ -60,9 +60,6 @@ static apr_status_t session_cookie_save(request_rec * r, session_rec * z) |
|
session_cookie_dir_conf *conf = ap_get_module_config(r->per_dir_config, |
|
&session_cookie_module); |
|
|
|
- /* don't cache auth protected pages */ |
|
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); |
|
- |
|
/* create RFC2109 compliant cookie */ |
|
if (conf->name_set) { |
|
if (z->encoded && z->encoded[0]) { |
|
@@ -162,6 +159,9 @@ static apr_status_t session_cookie_load(request_rec * r, session_rec ** z) |
|
/* put the session in the notes so we don't have to parse it again */ |
|
apr_table_setn(m->notes, note, (char *)zz); |
|
|
|
+ /* don't cache auth protected pages */ |
|
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private"); |
|
+ |
|
return OK; |
|
|
|
} |
|
diff --git a/modules/session/mod_session_dbd.c b/modules/session/mod_session_dbd.c |
|
index cf65e5a..20ef72e 100644 |
|
--- a/modules/session/mod_session_dbd.c |
|
+++ b/modules/session/mod_session_dbd.c |
|
@@ -243,6 +243,9 @@ static apr_status_t session_dbd_load(request_rec * r, session_rec ** z) |
|
/* put the session in the notes so we don't have to parse it again */ |
|
apr_table_setn(m->notes, note, (char *)zz); |
|
|
|
+ /* don't cache pages with a session */ |
|
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private"); |
|
+ |
|
return OK; |
|
|
|
} |
|
@@ -407,9 +410,6 @@ static apr_status_t session_dbd_save(request_rec * r, session_rec * z) |
|
if (conf->name_set || conf->name2_set) { |
|
char *oldkey = NULL, *newkey = NULL; |
|
|
|
- /* don't cache pages with a session */ |
|
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); |
|
- |
|
/* if the session is new or changed, make a new session ID */ |
|
if (z->uuid) { |
|
oldkey = apr_pcalloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); |
|
@@ -456,7 +456,7 @@ static apr_status_t session_dbd_save(request_rec * r, session_rec * z) |
|
else if (conf->peruser) { |
|
|
|
/* don't cache pages with a session */ |
|
- apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); |
|
+ apr_table_addn(r->headers_out, "Cache-Control", "no-cache, private"); |
|
|
|
if (r->user) { |
|
ret = dbd_save(r, r->user, r->user, z->encoded, z->expiry);
|
|
|