新增cache-pending接口函数tfe_get_cache_pending和tfe_put_cache_pending函数,用于
根据请求域和响应域判断是否应该缓存该HTTP会话
This commit is contained in:
352
cache/src/tango_cache_pending.cpp
vendored
Normal file
352
cache/src/tango_cache_pending.cpp
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
#include"proxy_cache.h"
|
||||
#include<assert.h>
|
||||
#include<string.h>
|
||||
#include<stdlib.h>
|
||||
#include<stdio.h>
|
||||
#include<stdbool.h>
|
||||
|
||||
|
||||
time_t get_time_value(const char* field_value, const char* field_type)
|
||||
{
|
||||
time_t time;
|
||||
char* time_value = NULL;
|
||||
field_value += strlen(field_type);
|
||||
field_value++;
|
||||
int len = strlen(field_value);
|
||||
time_value = (char *)malloc(sizeof(char)*len);
|
||||
int index = 0;
|
||||
while (field_value[index] != ',' && field_value[index] != '\r' && index < len)
|
||||
{
|
||||
time_value[index] = field_value[index];
|
||||
index++;
|
||||
}
|
||||
time_value[index] = '\0';
|
||||
time = (time_t)atol(time_value);
|
||||
free(time_value);
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
void get_request_freshness(const char *value, struct request_freshness* restrict)
|
||||
{
|
||||
const char* field_value = NULL;
|
||||
const char* cache_control_time[] = { "min-fresh", "max-age" };
|
||||
int i = 0;
|
||||
time_t relative_time;
|
||||
field_value = strstr(value, "min-fresh");
|
||||
if (field_value != NULL)
|
||||
{
|
||||
restrict->min_fresh = get_time_value(field_value, "min-fresh");;
|
||||
}
|
||||
|
||||
field_value = strstr(value, "max-age");
|
||||
if (field_value != NULL)
|
||||
{
|
||||
restrict->max_age = get_time_value(field_value, "max-age");;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum cache_pending_action request_cache_control(const char* value, struct request_freshness* restrict)
|
||||
{
|
||||
int i = 0;
|
||||
if (strstr(value, "no-cache") != NULL)
|
||||
{
|
||||
return VERIFY;
|
||||
}
|
||||
if (strstr(value, "no-store") != NULL)
|
||||
{
|
||||
return FORBIDDEN;
|
||||
}
|
||||
get_request_freshness(value, restrict);
|
||||
return ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
bool cache_vertify(const struct tfe_http_field *http_fields, size_t n_fields)
|
||||
{
|
||||
int i = 0;
|
||||
for (; i < n_fields; i++)
|
||||
{
|
||||
if ( http_fields[i].http_field == TLF_HTTP_IF_MATCH ||
|
||||
http_fields[i].http_field == TLF_HTTP_IF_NONE_MATCH ||
|
||||
http_fields[i].http_field == TLF_HTTP_IF_MODIFIED_SINCE ||
|
||||
http_fields[i].http_field == TLF_HTTP_IF_UNMODIFIED_SINCE )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char* get_head_value(const struct tfe_http_field *http_fields, size_t n_fields, enum tfe_http_std_field head_key)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < n_fields; i++)
|
||||
{
|
||||
if (http_fields[i].http_field == head_key)
|
||||
{
|
||||
return http_fields[i].value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
enum cache_pending_action get_pragma_action(const char * value)
|
||||
{
|
||||
const char *pragma_value = "no-cache";
|
||||
if (memcmp(value, pragma_value, strlen(pragma_value)) == 0)
|
||||
{
|
||||
return VERIFY;
|
||||
}
|
||||
return UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
enum cache_pending_action tfe_cache_get_pending(const struct tfe_http_field *request, size_t n_fields, struct request_freshness* restrict)
|
||||
{
|
||||
enum cache_pending_action res = UNDEFINED;
|
||||
int i = 0;
|
||||
int index = 0;
|
||||
const char *value = NULL;
|
||||
memset(restrict,0,sizeof(struct request_freshness));
|
||||
value = get_head_value(request, n_fields, TFE_HTTP_PRAGMA);
|
||||
if (value != NULL)
|
||||
{
|
||||
res = get_pragma_action(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = get_head_value(request, n_fields, TFE_HTTP_CACHE_CONTROL);
|
||||
if (value != NULL)
|
||||
{
|
||||
res = request_cache_control(value, restrict);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cache_vertify(request, n_fields))
|
||||
{
|
||||
res = VERIFY;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t absolute_to_relative_time(const char* gmt_time)
|
||||
{
|
||||
time_t expire_rel_time;
|
||||
struct tm expire_gmt_time;
|
||||
strptime(gmt_time, "%a, %d %b %Y %H:%M:%S GMT", &expire_gmt_time);
|
||||
expire_rel_time = mktime(&expire_gmt_time);
|
||||
return expire_rel_time;
|
||||
}
|
||||
|
||||
|
||||
bool is_standard_gmt_format(const char* value)
|
||||
{
|
||||
int str_len = strlen(value);
|
||||
if ((value[str_len - 1] == 'T') && (value[str_len - 2] == 'M') && (value[str_len - 3] == 'G'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
time_t get_relative_time(const char* value)
|
||||
{
|
||||
const char* temp_str = NULL;
|
||||
char * str_age = NULL;
|
||||
time_t time = 0;
|
||||
const char * cache_ctl_time[] = { "s-maxage","max-age" };//s-maxage优先级大于max-age优先级
|
||||
int i = 0;
|
||||
for (; i < 2; i++)
|
||||
{
|
||||
temp_str = strstr(value, cache_ctl_time[i]);
|
||||
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
time_t get_response_s_maxage(const char* cache_ctl)
|
||||
{
|
||||
const char* s_maxage = NULL;
|
||||
s_maxage = strstr(cache_ctl, "s-maxage");
|
||||
if (s_maxage != NULL)
|
||||
{
|
||||
return get_time_value(s_maxage, "s-maxage");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
time_t get_response_maxage(const char* cache_ctl)
|
||||
{
|
||||
const char* max_age = NULL;
|
||||
max_age = strstr(cache_ctl, "max-age");
|
||||
if (max_age != NULL)
|
||||
{
|
||||
return get_time_value(max_age, "max-age");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void get_response_freshness(const struct tfe_http_field *response, size_t n_fields, struct response_freshness* freshness)
|
||||
{
|
||||
time_t expire_rel_time = 0;
|
||||
time_t cur_rel_time = 0;
|
||||
struct tm cur_gmt_time;
|
||||
const char* field_value = NULL;
|
||||
field_value = get_head_value(response, n_fields, TFE_HTTP_CACHE_CONTROL);
|
||||
if (field_value != NULL)
|
||||
{
|
||||
freshness->timeout = get_response_s_maxage(field_value);
|
||||
if (freshness->timeout == 0)
|
||||
{
|
||||
freshness->timeout = get_response_maxage(field_value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
field_value = get_head_value(response, n_fields, TFE_HTTP_EXPIRES);
|
||||
if (field_value != NULL)
|
||||
{
|
||||
assert(is_standard_gmt_format(field_value));
|
||||
expire_rel_time = absolute_to_relative_time(field_value);
|
||||
const time_t cur_ct_time = time(NULL);
|
||||
if (gmtime_r(&cur_ct_time, &cur_gmt_time) == NULL)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
cur_rel_time = mktime(&cur_gmt_time);
|
||||
freshness->timeout = expire_rel_time - cur_rel_time;
|
||||
}
|
||||
}
|
||||
field_value = get_head_value(response, n_fields, TFE_HTTP_DATE);
|
||||
if (field_value != NULL)
|
||||
{
|
||||
assert(is_standard_gmt_format(field_value));
|
||||
freshness->date = absolute_to_relative_time(field_value);;
|
||||
}
|
||||
field_value = get_head_value(response, n_fields, TLF_HTTP_LAST_MODIFIED);
|
||||
if (field_value != NULL)
|
||||
{
|
||||
assert(is_standard_gmt_format(field_value));
|
||||
freshness->last_modified = absolute_to_relative_time(field_value);;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum cache_pending_action response_cache_control(const char* value)
|
||||
{
|
||||
const char *forbidden_vaule[] = {"no-store", "private"};
|
||||
const char *verify_vaule[] = { "no-cache", "must-revalidate","proxy-revalidate" };
|
||||
int i = 0;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (strstr(value, forbidden_vaule[i]) != NULL)
|
||||
{
|
||||
return FORBIDDEN;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (strstr(value, verify_vaule[i]) != NULL)
|
||||
{
|
||||
return VERIFY;
|
||||
}
|
||||
}
|
||||
return ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
enum cache_pending_action tfe_cache_put_pending(const struct tfe_http_field *response, size_t n_fields, struct response_freshness* freshness)
|
||||
{
|
||||
enum cache_pending_action res = UNDEFINED;
|
||||
int i = 0;
|
||||
int index = 0;
|
||||
const char *value = NULL;
|
||||
memset(freshness,0,sizeof(struct response_freshness));
|
||||
value = get_head_value(response, n_fields, TFE_HTTP_PRAGMA);
|
||||
if (value != NULL)
|
||||
{
|
||||
res = get_pragma_action(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = get_head_value(response, n_fields, TFE_HTTP_CACHE_CONTROL);
|
||||
if (value != NULL)
|
||||
{
|
||||
res = response_cache_control(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = get_head_value(response, n_fields, TFE_HTTP_EXPIRES);
|
||||
if (value != NULL)
|
||||
{
|
||||
res = ALLOWED;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res == ALLOWED)
|
||||
{
|
||||
get_response_freshness(response, n_fields, freshness);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("please input the head info\n");
|
||||
printf("first line input the head type and the num of head,0:request head 1:response head\n");
|
||||
printf("next line input the head field,date:10,pragma :14,expires:23,cache-control:25,If-Match:26,If-None-Match:27,If-Modified-since:28,If-Unmodified-since:29,Last-Modified:30\n");
|
||||
int head_type;
|
||||
int head_num = 0;
|
||||
scanf("%d %d", &head_type, &head_num);
|
||||
struct tfe_http_field *http_heads = (struct tfe_http_field *)malloc(sizeof(struct tfe_http_field)*head_num);
|
||||
printf("head type is %d and head_num is %d\n", head_type, head_num);
|
||||
int i = 0;
|
||||
for (; i < head_num; i++)
|
||||
{
|
||||
http_heads[i].value = (char *)malloc(sizeof(char) * 50);
|
||||
scanf("%d ", &(http_heads[i].http_field));
|
||||
fgets(http_heads[i].value, 50, stdin);
|
||||
int len = strlen(http_heads[i].value);
|
||||
http_heads[i].value[len - 1] = '\0';
|
||||
printf("head field is %d and head value is %s\n", http_heads[i].http_field, http_heads[i].value);
|
||||
}
|
||||
enum cache_pending_action res;
|
||||
struct request_freshness restrict;
|
||||
struct response_freshness freshness;
|
||||
switch (head_type)
|
||||
{
|
||||
case 0:
|
||||
res = tfe_cache_get_pending(http_heads, head_num, &restrict);
|
||||
printf(" request cache pending action is %d\n", res);
|
||||
printf("request min-fresh is %lu,max-age=%lu\n", restrict.min_fresh, restrict.max_age);
|
||||
break;
|
||||
case 1:
|
||||
res = tfe_cache_put_pending(http_heads, head_num, &freshness);
|
||||
printf(" request cache pending action is %d\n", res);
|
||||
printf("response date is %lu ,last-modified is %lu, timeout is %lu\n", freshness.date, freshness.last_modified, freshness.timeout);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < head_num; i++)
|
||||
{
|
||||
free(http_heads[i].value);
|
||||
}
|
||||
free(http_heads);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user