0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-25 08:12:37 +01:00

modules/client/root: Stream from aio -> chunked encoding -> you.

Next is the mmap() with ctx::wait for pf w/ mincore() ...
This commit is contained in:
Jason Volk 2018-03-22 00:45:49 -07:00
parent 51714d2b67
commit ce084a1df0

View file

@ -24,32 +24,120 @@ init_files()
}
}
static string_view
content_type(const mutable_buffer &out,
const string_view &filename,
const string_view &content);
resource::response
get_root(client &client, const resource::request &request)
get_root(client &client,
const resource::request &request)
try
{
const auto &path
{
!request.head.path? "index.html":
request.head.path == "/"? "index.html":
!request.head.path?
"index.html":
request.head.path == "/"?
"index.html":
request.head.path
};
auto it(files.find(lstrip(path, '/')));
auto it
{
files.find(lstrip(path, '/'))
};
if(it == end(files))
throw http::error{http::NOT_FOUND};
const auto &filename(it->second);
const std::string content
const auto &filename{it->second};
char content_buffer[24_KiB];
const string_view first_chunk
{
ircd::fs::read(filename)
fs::read(filename, content_buffer)
};
char content_type_buf[64];
resource::response
{
client,
http::OK,
content_type(content_type_buf, filename, first_chunk),
size(first_chunk) < sizeof(content_buffer)? size(first_chunk) : -1
};
if(size(first_chunk) < sizeof(content_buffer))
{
client.write_all(first_chunk);
return {};
}
char headbuf[64];
const unwind::exceptional terminate{[&headbuf, &client]
{
client.write_all("\r\n"_sv);
client.write_all(http::writechunk(headbuf, 0));
client.write_all("\r\n"_sv);
}};
client.write_all(http::writechunk(headbuf, size(first_chunk)));
client.write_all(first_chunk);
client.write_all("\r\n"_sv);
static const size_t max_chunk_length{48_KiB};
const unique_buffer<mutable_buffer> chunk_buffer
{
max_chunk_length
};
for(size_t offset(size(first_chunk));;)
{
const string_view chunk
{
fs::read(filename, chunk_buffer, offset)
};
if(empty(chunk))
break;
const string_view head
{
http::writechunk(headbuf, size(chunk))
};
client.write_all(head);
client.write_all(chunk);
client.write_all("\r\n"_sv);
offset += size(chunk);
if(size(chunk) < max_chunk_length)
break;
}
client.write_all(http::writechunk(headbuf, 0));
client.write_all("\r\n"_sv);
return {};
}
catch(const fs::filesystem_error &e)
{
throw http::error
{
http::NOT_FOUND //TODO: interp error_code
};
}
string_view
content_type(const mutable_buffer &out,
const string_view &filename,
const string_view &content)
{
const auto extension
{
rsplit(filename, '.').second
};
char content_type_buf[64];
string_view content_type; switch(hash(extension))
{
case hash("css"): content_type = "text/css; charset=utf-8"; break;
@ -71,15 +159,12 @@ get_root(client &client, const resource::request &request)
case hash("txt"): content_type = "text/plain; charset=utf-8"; break;
default:
{
content_type = magic::mime(content_type_buf, string_view{content});
content_type = magic::mime(out, content);
break;
}
}
return resource::response
{
client, string_view{content}, content_type
};
return content_type;
}
resource root_resource