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:
parent
51714d2b67
commit
ce084a1df0
1 changed files with 98 additions and 13 deletions
111
modules/root.cc
111
modules/root.cc
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue