implemented etag and if-none-match in http-fil.c
This commit is contained in:
parent
18eda3a6b5
commit
843ea8d8c1
@ -1242,7 +1242,7 @@ for (i = 0; i < 5; i++)
|
|||||||
//mio_bcstrtoskad (mio, "[""]:9988", &htts_bind_info.localaddr);
|
//mio_bcstrtoskad (mio, "[""]:9988", &htts_bind_info.localaddr);
|
||||||
mio_bcstrtoskad (mio, "0.0.0.0:9988", &htts_bind_info.localaddr);
|
mio_bcstrtoskad (mio, "0.0.0.0:9988", &htts_bind_info.localaddr);
|
||||||
htts_bind_info.options = MIO_DEV_SCK_BIND_REUSEADDR | MIO_DEV_SCK_BIND_REUSEPORT | MIO_DEV_SCK_BIND_IGNERR;
|
htts_bind_info.options = MIO_DEV_SCK_BIND_REUSEADDR | MIO_DEV_SCK_BIND_REUSEPORT | MIO_DEV_SCK_BIND_IGNERR;
|
||||||
htts_bind_info.options |= MIO_DEV_SCK_BIND_SSL;
|
//htts_bind_info.options |= MIO_DEV_SCK_BIND_SSL;
|
||||||
htts_bind_info.ssl_certfile = "localhost.crt";
|
htts_bind_info.ssl_certfile = "localhost.crt";
|
||||||
htts_bind_info.ssl_keyfile = "localhost.key";
|
htts_bind_info.ssl_keyfile = "localhost.key";
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
#define FILE_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH
|
#define FILE_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ struct file_state_t
|
|||||||
mio_foff_t cur_offset;
|
mio_foff_t cur_offset;
|
||||||
mio_bch_t peer_buf[8192];
|
mio_bch_t peer_buf[8192];
|
||||||
mio_tmridx_t peer_tmridx;
|
mio_tmridx_t peer_tmridx;
|
||||||
|
mio_bch_t peer_etag[128];
|
||||||
|
|
||||||
mio_svc_htts_cli_t* client;
|
mio_svc_htts_cli_t* client;
|
||||||
mio_http_version_t req_version; /* client request */
|
mio_http_version_t req_version; /* client request */
|
||||||
@ -77,6 +79,7 @@ struct file_state_t
|
|||||||
unsigned int ever_attempted_to_write_to_client: 1;
|
unsigned int ever_attempted_to_write_to_client: 1;
|
||||||
unsigned int client_disconnected: 1;
|
unsigned int client_disconnected: 1;
|
||||||
unsigned int client_htrd_recbs_changed: 1;
|
unsigned int client_htrd_recbs_changed: 1;
|
||||||
|
unsigned int etag_match: 1;
|
||||||
mio_oow_t req_content_length; /* client request content length */
|
mio_oow_t req_content_length; /* client request content length */
|
||||||
file_state_res_mode_t res_mode_to_cli;
|
file_state_res_mode_t res_mode_to_cli;
|
||||||
|
|
||||||
@ -207,9 +210,15 @@ static void file_state_mark_over (file_state_t* file_state, int over_bits)
|
|||||||
|
|
||||||
if (file_state->keep_alive)
|
if (file_state->keep_alive)
|
||||||
{
|
{
|
||||||
|
#if defined(TCP_CORK)
|
||||||
|
int tcp_cork = 0;
|
||||||
|
mio_dev_sck_setsockopt(file_state->client->sck, SOL_TCP, TCP_CORK, &tcp_cork, MIO_SIZEOF(tcp_cork));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* how to arrange to delete this file_state object and put the socket back to the normal waiting state??? */
|
/* how to arrange to delete this file_state object and put the socket back to the normal waiting state??? */
|
||||||
MIO_ASSERT (file_state->htts->mio, file_state->client->rsrc == (mio_svc_htts_rsrc_t*)file_state);
|
MIO_ASSERT (file_state->htts->mio, file_state->client->rsrc == (mio_svc_htts_rsrc_t*)file_state);
|
||||||
|
|
||||||
|
|
||||||
MIO_SVC_HTTS_RSRC_DETACH (file_state->client->rsrc);
|
MIO_SVC_HTTS_RSRC_DETACH (file_state->client->rsrc);
|
||||||
/* file_state must not be accessed from here down as it could have been destroyed */
|
/* file_state must not be accessed from here down as it could have been destroyed */
|
||||||
}
|
}
|
||||||
@ -452,9 +461,11 @@ static int file_state_send_header_to_client (file_state_t* file_state, int statu
|
|||||||
file_state->req_version.major, file_state->req_version.minor,
|
file_state->req_version.major, file_state->req_version.minor,
|
||||||
status_code, mio_http_status_to_bcstr(status_code),
|
status_code, mio_http_status_to_bcstr(status_code),
|
||||||
cli->htts->server_name, dtbuf,
|
cli->htts->server_name, dtbuf,
|
||||||
(force_close? "close": "keep-alive"),
|
(force_close? "close": "keep-alive")) == (mio_oow_t)-1) return -1;
|
||||||
content_length) == (mio_oow_t)-1) return -1;
|
|
||||||
|
|
||||||
|
/* TODO: content_type */
|
||||||
|
|
||||||
|
if (file_state->req_method == MIO_HTTP_GET && mio_becs_fcat(cli->sbuf, "ETag: %hs\r\n", file_state->peer_etag) == (mio_oow_t)-1) return -1;
|
||||||
if (status_code == 206 && mio_becs_fcat(cli->sbuf, "Content-Ranges: bytes %ju-%ju/%ju\r\n", (mio_uintmax_t)file_state->start_offset, (mio_uintmax_t)file_state->end_offset, (mio_uintmax_t)file_state->total_size) == (mio_oow_t)-1) return -1;
|
if (status_code == 206 && mio_becs_fcat(cli->sbuf, "Content-Ranges: bytes %ju-%ju/%ju\r\n", (mio_uintmax_t)file_state->start_offset, (mio_uintmax_t)file_state->end_offset, (mio_uintmax_t)file_state->total_size) == (mio_oow_t)-1) return -1;
|
||||||
if (mio_becs_fcat(cli->sbuf, "Content-Length: %ju\r\n\r\n", (mio_uintmax_t)content_length) == (mio_oow_t)-1) return -1;
|
if (mio_becs_fcat(cli->sbuf, "Content-Length: %ju\r\n\r\n", (mio_uintmax_t)content_length) == (mio_oow_t)-1) return -1;
|
||||||
|
|
||||||
@ -529,16 +540,33 @@ static int file_state_send_contents_to_client (file_state_t* file_state)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_range_header (file_state_t* file_state, mio_htre_t* req)
|
static MIO_INLINE int process_range_header (file_state_t* file_state, mio_htre_t* req)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const mio_htre_hdrval_t* tmp;
|
const mio_htre_hdrval_t* tmp;
|
||||||
|
mio_oow_t etag_len;
|
||||||
|
|
||||||
if (fstat(file_state->peer, &st) <= -1)
|
if (fstat(file_state->peer, &st) <= -1)
|
||||||
{
|
{
|
||||||
file_state_send_final_status_to_client (file_state, 500, 1);
|
file_state_send_final_status_to_client (file_state, 500, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file_state->req_method == MIO_HTTP_GET)
|
||||||
|
{
|
||||||
|
etag_len = mio_fmt_uintmax_to_bcstr(&file_state->peer_etag[0], MIO_COUNTOF(file_state->peer_etag), st.st_mtim.tv_sec, 16, -1, '\0', MIO_NULL);
|
||||||
|
file_state->peer_etag[etag_len++] = '-';
|
||||||
|
etag_len += mio_fmt_uintmax_to_bcstr(&file_state->peer_etag[etag_len], MIO_COUNTOF(file_state->peer_etag), st.st_mtim.tv_nsec, 16, -1, '\0', MIO_NULL);
|
||||||
|
file_state->peer_etag[etag_len++] = '-';
|
||||||
|
etag_len += mio_fmt_uintmax_to_bcstr(&file_state->peer_etag[etag_len], MIO_COUNTOF(file_state->peer_etag) - etag_len, st.st_size, 16, -1, '\0', MIO_NULL);
|
||||||
|
file_state->peer_etag[etag_len++] = '-';
|
||||||
|
etag_len += mio_fmt_uintmax_to_bcstr(&file_state->peer_etag[etag_len], MIO_COUNTOF(file_state->peer_etag) - etag_len, st.st_ino, 16, -1, '\0', MIO_NULL);
|
||||||
|
file_state->peer_etag[etag_len++] = '-';
|
||||||
|
mio_fmt_uintmax_to_bcstr (&file_state->peer_etag[etag_len], MIO_COUNTOF(file_state->peer_etag) - etag_len, st.st_dev, 16, -1, '\0', MIO_NULL);
|
||||||
|
|
||||||
|
tmp = mio_htre_getheaderval(req, "If-None-Match");
|
||||||
|
if (tmp && mio_comp_bcstr(file_state->peer_etag, tmp->ptr, 0) == 0) file_state->etag_match = 1;
|
||||||
|
}
|
||||||
file_state->end_offset = st.st_size;
|
file_state->end_offset = st.st_size;
|
||||||
|
|
||||||
tmp = mio_htre_getheaderval(req, "Range"); /* TODO: support multiple ranges? */
|
tmp = mio_htre_getheaderval(req, "Range"); /* TODO: support multiple ranges? */
|
||||||
@ -733,7 +761,7 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t*
|
|||||||
else if (req->flags & MIO_HTRE_ATTR_EXPECT)
|
else if (req->flags & MIO_HTRE_ATTR_EXPECT)
|
||||||
{
|
{
|
||||||
/* 417 Expectation Failed */
|
/* 417 Expectation Failed */
|
||||||
file_state_send_final_status_to_client(file_state, 417, 1);
|
file_state_send_final_status_to_client (file_state, 417, 1);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,11 +810,27 @@ int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t*
|
|||||||
|
|
||||||
if (file_state->req_method == MIO_HTTP_GET)
|
if (file_state->req_method == MIO_HTTP_GET)
|
||||||
{
|
{
|
||||||
if (file_state_send_header_to_client(file_state, 200, 0) <= -1 ||
|
if (file_state->etag_match)
|
||||||
file_state_send_contents_to_client(file_state) <= -1) goto oops;
|
{
|
||||||
|
/* 304 not modified */
|
||||||
|
if (file_state_send_final_status_to_client(file_state, 304, 0) <= -1) goto oops;
|
||||||
|
file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER | FILE_STATE_OVER_WRITE_TO_PEER);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* normal full transfer */
|
||||||
|
#if defined(TCP_CORK)
|
||||||
|
int tcp_cork = 1;
|
||||||
|
mio_dev_sck_setsockopt(file_state->client->sck, SOL_TCP, TCP_CORK, &tcp_cork, MIO_SIZEOF(tcp_cork));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (file_state_send_header_to_client(file_state, 200, 0) <= -1 ||
|
||||||
|
file_state_send_contents_to_client(file_state) <= -1) goto oops;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (file_state->req_method == MIO_HTTP_HEAD)
|
else if (file_state->req_method == MIO_HTTP_HEAD)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (file_state_send_header_to_client(file_state, 200, 0) <= -1) goto oops;
|
if (file_state_send_header_to_client(file_state, 200, 0) <= -1) goto oops;
|
||||||
file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER | FILE_STATE_OVER_WRITE_TO_PEER);
|
file_state_mark_over (file_state, FILE_STATE_OVER_READ_FROM_PEER | FILE_STATE_OVER_WRITE_TO_PEER);
|
||||||
}
|
}
|
||||||
|
@ -624,6 +624,9 @@ static int dev_sck_writev_stateful (mio_dev_t* dev, const mio_iovec_t* iov, mio_
|
|||||||
#if defined(MSG_NOSIGNAL)
|
#if defined(MSG_NOSIGNAL)
|
||||||
flags |= MSG_NOSIGNAL;
|
flags |= MSG_NOSIGNAL;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(MSG_DONTWAIT)
|
||||||
|
flags |= MSG_DONTWAIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_SENDMSG)
|
#if defined(HAVE_SENDMSG)
|
||||||
MIO_MEMSET (&msg, 0, MIO_SIZEOF(msg));
|
MIO_MEMSET (&msg, 0, MIO_SIZEOF(msg));
|
||||||
@ -675,6 +678,7 @@ static int dev_sck_writev_stateless (mio_dev_t* dev, const mio_iovec_t* iov, mio
|
|||||||
mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev;
|
mio_dev_sck_t* rdev = (mio_dev_sck_t*)dev;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
ssize_t x;
|
ssize_t x;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
MIO_MEMSET (&msg, 0, MIO_SIZEOF(msg));
|
MIO_MEMSET (&msg, 0, MIO_SIZEOF(msg));
|
||||||
if (MIO_LIKELY(dstaddr))
|
if (MIO_LIKELY(dstaddr))
|
||||||
@ -685,7 +689,15 @@ static int dev_sck_writev_stateless (mio_dev_t* dev, const mio_iovec_t* iov, mio
|
|||||||
msg.msg_iov = (struct iovec*)iov;
|
msg.msg_iov = (struct iovec*)iov;
|
||||||
msg.msg_iovlen = *iovcnt;
|
msg.msg_iovlen = *iovcnt;
|
||||||
|
|
||||||
x = sendmsg(rdev->hnd, &msg, 0);
|
|
||||||
|
#if defined(MSG_NOSIGNAL)
|
||||||
|
flags |= MSG_NOSIGNAL;
|
||||||
|
#endif
|
||||||
|
#if defined(MSG_DONTWAIT)
|
||||||
|
flags |= MSG_DONTWAIT;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
x = sendmsg(rdev->hnd, &msg, flags);
|
||||||
if (x <= -1)
|
if (x <= -1)
|
||||||
{
|
{
|
||||||
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
|
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
|
||||||
|
Loading…
Reference in New Issue
Block a user