MINOR: samples: add the http_date([<offset>]) sample converter.
Converts an integer supposed to contain a date since epoch to
a string representing this date in a format suitable for use
in HTTP header fields. If an offset value is specified, then
it is a number of seconds that is added to the date before the
conversion is operated. This is particularly useful to emit
Date header fields, Expires values in responses when combined
with a positive offset, or Last-Modified values when the
offset is negative.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 58e4fa5..2c8fadf 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -8720,6 +8720,15 @@
the same server. The mask can be passed in dotted form (eg:
255.255.255.0) or in CIDR form (eg: 24).
+ http_date([<offset>])
+ Converts an integer supposed to contain a date since epoch to
+ a string representing this date in a format suitable for use
+ in HTTP header fields. If an offset value is specified, then
+ it is a number of seconds that is added to the date before the
+ conversion is operated. This is particularly useful to emit
+ Date header fields, Expires values in responses when combined
+ with a positive offset, or Last-Modified values when the
+ offset is negative.
7.3.1. Fetching samples from internal states
--------------------------------------------
@@ -8806,6 +8815,12 @@
If an offset value is specified, then it is a number of seconds that is added
to the current date before returning the value. This is particularly useful
to compute relative dates, as both positive and negative offsets are allowed.
+ It is useful combined with the http_date converter.
+
+ Example :
+
+ # set an expires header to now+1 hour in every response
+ http-response set-header Expires %[date(3600),http_date]
env(<name>) : string
Returns a string containing the value of environment variable <name>. As a
diff --git a/src/proto_http.c b/src/proto_http.c
index 7e38b68..ebb7556 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -10117,6 +10117,35 @@
return 1;
}
+/* takes an UINT value on input supposed to represent the time since EPOCH,
+ * adds an optional offset found in args[0] and emits a string representing
+ * the date in RFC-1123/5322 format.
+ */
+static int sample_conv_http_date(const struct arg *args, struct sample *smp)
+{
+ const char day[7][4] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+ const char mon[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+ struct chunk *temp;
+ struct tm *tm;
+ time_t curr_date = smp->data.uint;
+
+ /* add offset */
+ if (args && (args[0].type == ARGT_SINT || args[0].type == ARGT_UINT))
+ curr_date += args[0].data.sint;
+
+ tm = gmtime(&curr_date);
+
+ temp = get_trash_chunk();
+ temp->len = snprintf(temp->str, temp->size - temp->len,
+ "%s, %02d %s %04d %02d:%02d:%02d GMT",
+ day[tm->tm_wday], tm->tm_mday, mon[tm->tm_mon], 1900+tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ smp->data.str = *temp;
+ smp->type = SMP_T_STR;
+ return 1;
+}
+
/************************************************************************/
/* All supported ACL keywords must be declared here. */
/************************************************************************/
@@ -10299,11 +10328,18 @@
}};
+/* Note: must not be declared <const> as its list will be overwritten */
+static struct sample_conv_kw_list sample_conv_kws = {ILH, {
+ { "http_date", sample_conv_http_date, ARG1(0,SINT), NULL, SMP_T_UINT, SMP_T_STR },
+ { NULL, NULL, 0, 0, 0 },
+}};
+
__attribute__((constructor))
static void __http_protocol_init(void)
{
acl_register_keywords(&acl_kws);
sample_register_fetches(&sample_fetch_keywords);
+ sample_register_convs(&sample_conv_kws);
}