enhanced httpd to support if-modified-since
This commit is contained in:
parent
7466287f93
commit
2179c2a88b
@ -64,6 +64,8 @@
|
||||
(((qse_ntime_t)(sec) * QSE_MSECS_PER_SEC) + ((qse_ntime_t)(nsec) / QSE_NSECS_PER_MSEC))
|
||||
|
||||
#define QSE_SEC_TO_MSEC(sec) ((sec) * QSE_MSECS_PER_SEC)
|
||||
#define QSE_MSEC_TO_SEC(sec) ((sec) / QSE_MSECS_PER_SEC)
|
||||
|
||||
/**
|
||||
* The qse_ntime_t type defines a numeric time type expressed in the
|
||||
* number of milliseconds since the Epoch (00:00:00 UTC, Jan 1, 1970).
|
||||
|
@ -180,12 +180,10 @@ int qse_parsehttprange (
|
||||
qse_http_range_t* range
|
||||
);
|
||||
|
||||
/*
|
||||
int qse_parsehttptime (
|
||||
const qse_mchar_t* str,
|
||||
qse_ntime_t* t
|
||||
qse_ntime_t* nt
|
||||
);
|
||||
*/
|
||||
|
||||
qse_mchar_t* qse_fmthttptime (
|
||||
qse_ntime_t nt,
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <qse/net/htrd.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include "../cmn/mem.h"
|
||||
|
||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (htrd)
|
||||
@ -185,11 +186,10 @@ void qse_htrd_fini (qse_htrd_t* htrd)
|
||||
#endif
|
||||
}
|
||||
|
||||
static qse_mchar_t* parse_initial_line (
|
||||
qse_htrd_t* htrd, qse_mchar_t* line)
|
||||
static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
|
||||
{
|
||||
qse_mchar_t* p = line;
|
||||
qse_mcstr_t tmp;
|
||||
qse_mxstr_t tmp;
|
||||
|
||||
#if 0
|
||||
/* ignore leading spaces excluding crlf */
|
||||
@ -293,7 +293,9 @@ static qse_mchar_t* parse_initial_line (
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
qse_mchar_t* out;
|
||||
#endif
|
||||
qse_mcstr_t param;
|
||||
|
||||
/* skip spaces */
|
||||
|
@ -189,44 +189,127 @@ int qse_parsehttprange (const qse_mchar_t* str, qse_http_range_t* range)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int qse_parsehttptime (const qse_mchar_t* str, qse_ntime_t* t)
|
||||
typedef struct mname_t mname_t;
|
||||
struct mname_t
|
||||
{
|
||||
/* TODO: */
|
||||
return -1;
|
||||
const qse_mchar_t* s;
|
||||
const qse_mchar_t* l;
|
||||
};
|
||||
|
||||
static mname_t wday_name[] =
|
||||
{
|
||||
{ QSE_MT("Sun"), QSE_MT("Sunday") },
|
||||
{ QSE_MT("Mon"), QSE_MT("Monday") },
|
||||
{ QSE_MT("Tue"), QSE_MT("Tuesday") },
|
||||
{ QSE_MT("Wed"), QSE_MT("Wednesday") },
|
||||
{ QSE_MT("Thu"), QSE_MT("Thursday") },
|
||||
{ QSE_MT("Fri"), QSE_MT("Friday") },
|
||||
{ QSE_MT("Sat"), QSE_MT("Saturday") }
|
||||
};
|
||||
|
||||
static mname_t mon_name[] =
|
||||
{
|
||||
{ QSE_MT("Jan"), QSE_MT("January") },
|
||||
{ QSE_MT("Feb"), QSE_MT("February") },
|
||||
{ QSE_MT("Mar"), QSE_MT("March") },
|
||||
{ QSE_MT("Apr"), QSE_MT("April") },
|
||||
{ QSE_MT("May"), QSE_MT("May") },
|
||||
{ QSE_MT("Jun"), QSE_MT("June") },
|
||||
{ QSE_MT("Jul"), QSE_MT("July") },
|
||||
{ QSE_MT("Aug"), QSE_MT("August") },
|
||||
{ QSE_MT("Sep"), QSE_MT("September") },
|
||||
{ QSE_MT("Oct"), QSE_MT("October") },
|
||||
{ QSE_MT("Nov"), QSE_MT("November") },
|
||||
{ QSE_MT("Dec"), QSE_MT("December") }
|
||||
};
|
||||
|
||||
int qse_parsehttptime (const qse_mchar_t* str, qse_ntime_t* nt)
|
||||
{
|
||||
qse_btime_t bt;
|
||||
const qse_mchar_t* word;
|
||||
qse_size_t wlen, i;
|
||||
|
||||
/* TODO: support more formats */
|
||||
|
||||
QSE_MEMSET (&bt, 0, QSE_SIZEOF(bt));
|
||||
|
||||
/* weekday */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
for (word = str; QSE_ISMALPHA(*str); str++);
|
||||
wlen = str - word;
|
||||
for (i = 0; i < QSE_COUNTOF(wday_name); i++)
|
||||
{
|
||||
if (qse_mbsxcmp (word, wlen, wday_name[i].s) == 0)
|
||||
{
|
||||
bt.wday = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= QSE_COUNTOF(wday_name)) return -1;
|
||||
|
||||
/* comma - i'm just loose as i don't care if it doesn't exist */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
if (*str == QSE_MT(',')) str++;
|
||||
|
||||
/* day */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
if (!QSE_ISMDIGIT(*str)) return -1;
|
||||
do bt.mday = bt.mday * 10 + *str++ - QSE_MT('0'); while (QSE_ISMDIGIT(*str));
|
||||
|
||||
/* month */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
for (word = str; QSE_ISMALPHA(*str); str++);
|
||||
wlen = str - word;
|
||||
for (i = 0; i < QSE_COUNTOF(mon_name); i++)
|
||||
{
|
||||
if (qse_mbsxcmp (word, wlen, mon_name[i].s) == 0)
|
||||
{
|
||||
bt.mon = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= QSE_COUNTOF(mon_name)) return -1;
|
||||
|
||||
/* year */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
if (!QSE_ISMDIGIT(*str)) return -1;
|
||||
do bt.year = bt.year * 10 + *str++ - QSE_MT('0'); while (QSE_ISMDIGIT(*str));
|
||||
bt.year -= QSE_BTIME_YEAR_BASE;
|
||||
|
||||
/* hour */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
if (!QSE_ISMDIGIT(*str)) return -1;
|
||||
do bt.hour = bt.hour * 10 + *str++ - QSE_MT('0'); while (QSE_ISMDIGIT(*str));
|
||||
if (*str != QSE_MT(':')) return -1;
|
||||
str++;
|
||||
|
||||
/* min */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
if (!QSE_ISMDIGIT(*str)) return -1;
|
||||
do bt.min = bt.min * 10 + *str++ - QSE_MT('0'); while (QSE_ISMDIGIT(*str));
|
||||
if (*str != QSE_MT(':')) return -1;
|
||||
str++;
|
||||
|
||||
/* sec */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
if (!QSE_ISMDIGIT(*str)) return -1;
|
||||
do bt.sec = bt.sec * 10 + *str++ - QSE_MT('0'); while (QSE_ISMDIGIT(*str));
|
||||
|
||||
/* GMT */
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
for (word = str; QSE_ISMALPHA(*str); str++);
|
||||
wlen = str - word;
|
||||
if (qse_mbsxcmp (word, wlen, QSE_MT("GMT")) != 0) return -1;
|
||||
|
||||
while (QSE_ISMSPACE(*str)) str++;
|
||||
if (*str != QSE_MT('\0')) return -1;
|
||||
|
||||
return qse_timegm (&bt, nt);
|
||||
}
|
||||
#endif
|
||||
|
||||
qse_mchar_t* qse_fmthttptime (
|
||||
qse_ntime_t nt, qse_mchar_t* buf, qse_size_t bufsz)
|
||||
{
|
||||
static const qse_mchar_t* wday_name[] =
|
||||
{
|
||||
QSE_MT("Sun"),
|
||||
QSE_MT("Mon"),
|
||||
QSE_MT("Tue"),
|
||||
QSE_MT("Wed"),
|
||||
QSE_MT("Thu"),
|
||||
QSE_MT("Fri"),
|
||||
QSE_MT("Sat")
|
||||
};
|
||||
|
||||
static const qse_mchar_t* mon_name[] =
|
||||
{
|
||||
QSE_MT("Jan"),
|
||||
QSE_MT("Feb"),
|
||||
QSE_MT("Mar"),
|
||||
QSE_MT("Apr"),
|
||||
QSE_MT("May"),
|
||||
QSE_MT("Jun"),
|
||||
QSE_MT("Jul"),
|
||||
QSE_MT("Aug"),
|
||||
QSE_MT("Sep"),
|
||||
QSE_MT("Oct"),
|
||||
QSE_MT("Nov"),
|
||||
QSE_MT("Dec")
|
||||
};
|
||||
|
||||
qse_btime_t bt;
|
||||
|
||||
qse_gmtime (nt, &bt);
|
||||
@ -234,9 +317,9 @@ qse_mchar_t* qse_fmthttptime (
|
||||
/* TODO: avoid using snprintf () */
|
||||
snprintf (buf, bufsz,
|
||||
QSE_MT("%s, %d %s %d %02d:%02d:%02d GMT"),
|
||||
wday_name[bt.wday],
|
||||
wday_name[bt.wday].s,
|
||||
bt.mday,
|
||||
mon_name[bt.mon],
|
||||
mon_name[bt.mon].s,
|
||||
bt.year + QSE_BTIME_YEAR_BASE,
|
||||
bt.hour, bt.min, bt.sec);
|
||||
|
||||
|
@ -227,6 +227,23 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
|
||||
{
|
||||
qse_mchar_t b_fsize[64];
|
||||
|
||||
if (file->if_modified_since > 0 &&
|
||||
QSE_MSEC_TO_SEC(st.mtime) <= QSE_MSEC_TO_SEC(file->if_modified_since))
|
||||
{
|
||||
/* i've converted milliseconds to seconds before comparison
|
||||
* because st.mtime has the actual milliseconds less than 1 second
|
||||
* while if_modified_since doesn't have such small milliseconds */
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 304 Not Modified\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Length: 0\r\n\r\n"),
|
||||
file->version.major, file->version.minor,
|
||||
qse_httpd_getname (httpd),
|
||||
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
|
||||
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close"))
|
||||
);
|
||||
goto no_file_send;
|
||||
}
|
||||
|
||||
qse_fmtuintmaxtombs (b_fsize, QSE_COUNTOF(b_fsize), st.size, 10, -1, QSE_MT('\0'), QSE_NULL);
|
||||
|
||||
/* wget 1.8.2 set 'Connection: keep-alive' in the http 1.0 header.
|
||||
@ -288,15 +305,15 @@ qse_httpd_task_t* qse_httpd_entaskfile (
|
||||
data.range.type = QSE_HTTP_RANGE_NONE;
|
||||
}
|
||||
|
||||
data.if_modified_since = QSE_TYPE_MIN(qse_ntime_t);
|
||||
/*
|
||||
TODO: If-Modified-Since...
|
||||
/* TODO: support Etag and If-None-Match */
|
||||
data.if_modified_since = 0; /* 0 should be old enough */
|
||||
tmp = qse_htre_getheaderval(req, QSE_MT("If-Modified-Since"));
|
||||
if (tmp)
|
||||
{
|
||||
qse_httpd_parsegmtime (tmp, &
|
||||
while (tmp->next) tmp = tmp->next; /* get the last value */
|
||||
if (qse_parsehttptime (tmp->ptr, &data.if_modified_since) <= -1)
|
||||
data.if_modified_since = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||
task.init = task_init_file;
|
||||
|
Loading…
Reference in New Issue
Block a user