http_static: added last-modified header
Type: improvement Change-Id: I492df92ef25f9c0cd57fc8980500b58bebaa94c6 Signed-off-by: Adrian Villin <avillin@cisco.com>
This commit is contained in:
Adrian Villin
committed by
Florin Coras
parent
8792e5c5c5
commit
7e6606ab4e
@ -553,6 +553,8 @@ func HttpStaticFileHandlerTestFunction(s *NoTopoSuite, max_age string) {
|
||||
|
||||
content := "<html><body><p>Hello</p></body></html>"
|
||||
content2 := "<html><body><p>Page</p></body></html>"
|
||||
currentDate := time.Now().In(time.FixedZone("GMT", 0)).Format(http.TimeFormat)[:17]
|
||||
|
||||
vpp := s.GetContainerByName("vpp").VppInstance
|
||||
vpp.Container.Exec("mkdir -p " + wwwRootPath)
|
||||
err := vpp.Container.CreateFile(wwwRootPath+"/index.html", content)
|
||||
@ -568,11 +570,16 @@ func HttpStaticFileHandlerTestFunction(s *NoTopoSuite, max_age string) {
|
||||
resp, err := client.Do(req)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
defer resp.Body.Close()
|
||||
|
||||
s.Log(DumpHttpResp(resp, true))
|
||||
s.AssertEqual(200, resp.StatusCode)
|
||||
s.AssertContains(resp.Header.Get("Content-Type"), "html")
|
||||
s.AssertContains(resp.Header.Get("Cache-Control"), "max-age="+max_age)
|
||||
// only checking date
|
||||
s.AssertContains(resp.Header.Get("Last-Modified"), currentDate)
|
||||
s.AssertEqual(len(resp.Header.Get("Last-Modified")), 29)
|
||||
s.AssertEqual(int64(len([]rune(content))), resp.ContentLength)
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
s.AssertEqual(string(body), content)
|
||||
@ -589,6 +596,7 @@ func HttpStaticFileHandlerTestFunction(s *NoTopoSuite, max_age string) {
|
||||
s.AssertContains(resp.Header.Get("Content-Type"), "html")
|
||||
s.AssertContains(resp.Header.Get("Cache-Control"), "max-age="+max_age)
|
||||
s.AssertEqual(int64(len([]rune(content))), resp.ContentLength)
|
||||
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
s.AssertEqual(string(body), content)
|
||||
@ -603,6 +611,7 @@ func HttpStaticFileHandlerTestFunction(s *NoTopoSuite, max_age string) {
|
||||
s.AssertContains(resp.Header.Get("Content-Type"), "html")
|
||||
s.AssertContains(resp.Header.Get("Cache-Control"), "max-age="+max_age)
|
||||
s.AssertEqual(int64(len([]rune(content2))), resp.ContentLength)
|
||||
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
s.AssertNil(err, fmt.Sprint(err))
|
||||
s.AssertEqual(string(body), content2)
|
||||
@ -828,7 +837,7 @@ func HttpStaticBuildInUrlPostIfStatsTest(s *NoTopoSuite) {
|
||||
}
|
||||
|
||||
func HttpStaticMacTimeTest(s *NoTopoSuite) {
|
||||
currentDate := time.Now().In(time.FixedZone("GMT", 0)).Format(http.TimeFormat)
|
||||
currentDate := time.Now().In(time.FixedZone("GMT", 0)).Format(http.TimeFormat)[:17]
|
||||
vpp := s.GetContainerByName("vpp").VppInstance
|
||||
serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
|
||||
s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
|
||||
@ -848,6 +857,8 @@ func HttpStaticMacTimeTest(s *NoTopoSuite) {
|
||||
s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).Ip4AddressString())
|
||||
s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).HwAddress.String())
|
||||
s.AssertContains(resp.Header.Get("Content-Type"), "json")
|
||||
s.AssertEqual(len(resp.Header.Get("Date")), 29)
|
||||
// only checking date
|
||||
s.AssertContains(resp.Header.Get("Date"), currentDate)
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <vppinfra/bihash_template.c>
|
||||
#include <vppinfra/unix.h>
|
||||
#include <vlib/vlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <vppinfra/time_range.h>
|
||||
|
||||
static void
|
||||
hss_cache_lock (hss_cache_t *hc)
|
||||
@ -153,7 +155,7 @@ lru_update (hss_cache_t *hc, hss_cache_entry_t *ep, f64 now)
|
||||
|
||||
static void
|
||||
hss_cache_attach_entry (hss_cache_t *hc, u32 ce_index, u8 **data,
|
||||
u64 *data_len)
|
||||
u64 *data_len, u8 **last_modified)
|
||||
{
|
||||
hss_cache_entry_t *ce;
|
||||
|
||||
@ -162,6 +164,7 @@ hss_cache_attach_entry (hss_cache_t *hc, u32 ce_index, u8 **data,
|
||||
ce->inuse++;
|
||||
*data = ce->data;
|
||||
*data_len = vec_len (ce->data);
|
||||
*last_modified = ce->last_modified;
|
||||
|
||||
/* Update the cache entry, mark it in-use */
|
||||
lru_update (hc, ce, vlib_time_now (vlib_get_main ()));
|
||||
@ -209,16 +212,15 @@ hss_cache_lookup (hss_cache_t *hc, u8 *path)
|
||||
|
||||
u32
|
||||
hss_cache_lookup_and_attach (hss_cache_t *hc, u8 *path, u8 **data,
|
||||
u64 *data_len)
|
||||
u64 *data_len, u8 **last_modified)
|
||||
{
|
||||
u32 ce_index;
|
||||
|
||||
/* Make sure nobody removes the entry while we look it up */
|
||||
hss_cache_lock (hc);
|
||||
|
||||
ce_index = hss_cache_lookup (hc, path);
|
||||
if (ce_index != ~0)
|
||||
hss_cache_attach_entry (hc, ce_index, data, data_len);
|
||||
hss_cache_attach_entry (hc, ce_index, data, data_len, last_modified);
|
||||
|
||||
hss_cache_unlock (hc);
|
||||
|
||||
@ -260,6 +262,7 @@ hss_cache_do_evictions (hss_cache_t *hc)
|
||||
hc->cache_evictions++;
|
||||
vec_free (ce->filename);
|
||||
vec_free (ce->data);
|
||||
vec_free (ce->last_modified);
|
||||
|
||||
if (hc->debug_level > 1)
|
||||
clib_warning ("pool put index %d", ce - hc->cache_pool);
|
||||
@ -271,13 +274,15 @@ hss_cache_do_evictions (hss_cache_t *hc)
|
||||
}
|
||||
|
||||
u32
|
||||
hss_cache_add_and_attach (hss_cache_t *hc, u8 *path, u8 **data, u64 *data_len)
|
||||
hss_cache_add_and_attach (hss_cache_t *hc, u8 *path, u8 **data, u64 *data_len,
|
||||
u8 **last_modified)
|
||||
{
|
||||
BVT (clib_bihash_kv) kv;
|
||||
hss_cache_entry_t *ce;
|
||||
clib_error_t *error;
|
||||
u8 *file_data;
|
||||
u32 ce_index;
|
||||
struct stat dm;
|
||||
|
||||
hss_cache_lock (hc);
|
||||
|
||||
@ -298,11 +303,17 @@ hss_cache_add_and_attach (hss_cache_t *hc, u8 *path, u8 **data, u64 *data_len)
|
||||
pool_get_zero (hc->cache_pool, ce);
|
||||
ce->filename = vec_dup (path);
|
||||
ce->data = file_data;
|
||||
if (stat ((char *) path, &dm) == 0)
|
||||
{
|
||||
ce->last_modified =
|
||||
format (0, "%U GMT", format_clib_timebase_time, (f64) dm.st_mtime);
|
||||
}
|
||||
|
||||
/* Attach cache entry without additional lock */
|
||||
ce->inuse++;
|
||||
*data = file_data;
|
||||
*data_len = vec_len (file_data);
|
||||
*last_modified = ce->last_modified;
|
||||
lru_add (hc, ce, vlib_time_now (vlib_get_main ()));
|
||||
|
||||
hc->cache_size += vec_len (ce->data);
|
||||
@ -364,6 +375,7 @@ hss_cache_clear (hss_cache_t *hc)
|
||||
hc->cache_evictions++;
|
||||
vec_free (ce->filename);
|
||||
vec_free (ce->data);
|
||||
vec_free (ce->last_modified);
|
||||
if (hc->debug_level > 1)
|
||||
clib_warning ("pool put index %d", ce - hc->cache_pool);
|
||||
pool_put (hc->cache_pool, ce);
|
||||
|
@ -22,6 +22,9 @@ typedef struct hss_cache_entry_
|
||||
{
|
||||
/** Name of the file */
|
||||
u8 *filename;
|
||||
/** Last modified date, format:
|
||||
* <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT */
|
||||
u8 *last_modified;
|
||||
/** Contents of the file, as a u8 * vector */
|
||||
u8 *data;
|
||||
/** Last time the cache entry was used */
|
||||
@ -58,9 +61,9 @@ typedef struct hss_cache_
|
||||
} hss_cache_t;
|
||||
|
||||
u32 hss_cache_lookup_and_attach (hss_cache_t *hc, u8 *path, u8 **data,
|
||||
u64 *data_len);
|
||||
u64 *data_len, u8 **last_modified);
|
||||
u32 hss_cache_add_and_attach (hss_cache_t *hc, u8 *path, u8 **data,
|
||||
u64 *data_len);
|
||||
u64 *data_len, u8 **last_modified);
|
||||
void hss_cache_detach_entry (hss_cache_t *hc, u32 ce_index);
|
||||
u32 hss_cache_clear (hss_cache_t *hc);
|
||||
void hss_cache_init (hss_cache_t *hc, uword cache_size, u8 debug_level);
|
||||
|
@ -411,6 +411,7 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
|
||||
u8 *path, *sanitized_path;
|
||||
u32 ce_index;
|
||||
http_content_type_t type;
|
||||
u8 *last_modified;
|
||||
|
||||
/* Feature not enabled */
|
||||
if (!hsm->www_root)
|
||||
@ -435,8 +436,8 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
|
||||
|
||||
hs->data_offset = 0;
|
||||
|
||||
ce_index =
|
||||
hss_cache_lookup_and_attach (&hsm->cache, path, &hs->data, &hs->data_len);
|
||||
ce_index = hss_cache_lookup_and_attach (&hsm->cache, path, &hs->data,
|
||||
&hs->data_len, &last_modified);
|
||||
if (ce_index == ~0)
|
||||
{
|
||||
if (!file_path_is_valid (path))
|
||||
@ -455,8 +456,8 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
|
||||
sc = try_index_file (hsm, hs, path);
|
||||
goto done;
|
||||
}
|
||||
ce_index =
|
||||
hss_cache_add_and_attach (&hsm->cache, path, &hs->data, &hs->data_len);
|
||||
ce_index = hss_cache_add_and_attach (&hsm->cache, path, &hs->data,
|
||||
&hs->data_len, &last_modified);
|
||||
if (ce_index == ~0)
|
||||
{
|
||||
sc = HTTP_STATUS_INTERNAL_ERROR;
|
||||
@ -478,6 +479,9 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt,
|
||||
http_add_header (
|
||||
&hs->resp_headers, http_header_name_token (HTTP_HEADER_CACHE_CONTROL),
|
||||
(const char *) hsm->max_age_formatted, vec_len (hsm->max_age_formatted));
|
||||
http_add_header (&hs->resp_headers,
|
||||
http_header_name_token (HTTP_HEADER_LAST_MODIFIED),
|
||||
(const char *) last_modified, vec_len (last_modified));
|
||||
|
||||
done:
|
||||
vec_free (sanitized_path);
|
||||
|
Reference in New Issue
Block a user