mirror of
https://github.com/matrix-construct/construct
synced 2025-02-18 09:40:12 +01:00
ircd::resource: Add chunked encoding response suite.
This commit is contained in:
parent
e35338b5b2
commit
deb1a0a979
2 changed files with 136 additions and 0 deletions
|
@ -136,6 +136,8 @@ struct ircd::resource::request::object
|
||||||
|
|
||||||
struct ircd::resource::response
|
struct ircd::resource::response
|
||||||
{
|
{
|
||||||
|
struct chunked;
|
||||||
|
|
||||||
response(client &, const http::code &, const string_view &content_type, const size_t &content_length, const string_view &headers = {});
|
response(client &, const http::code &, const string_view &content_type, const size_t &content_length, const string_view &headers = {});
|
||||||
response(client &, const string_view &str, const string_view &content_type, const http::code &, const vector_view<const http::header> &);
|
response(client &, const string_view &str, const string_view &content_type, const http::code &, const vector_view<const http::header> &);
|
||||||
response(client &, const string_view &str, const string_view &content_type, const http::code & = http::OK, const string_view &headers = {});
|
response(client &, const string_view &str, const string_view &content_type, const http::code & = http::OK, const string_view &headers = {});
|
||||||
|
@ -151,6 +153,24 @@ struct ircd::resource::response
|
||||||
response() = default;
|
response() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ircd::resource::response::chunked
|
||||||
|
:resource::response
|
||||||
|
{
|
||||||
|
client *c {nullptr};
|
||||||
|
|
||||||
|
size_t write(const const_buffer &chunk);
|
||||||
|
bool finish();
|
||||||
|
|
||||||
|
chunked(client &, const http::code &, const string_view &content_type, const string_view &headers = {});
|
||||||
|
chunked(client &, const http::code &, const string_view &content_type, const vector_view<const http::header> &);
|
||||||
|
chunked(client &, const http::code &, const vector_view<const http::header> &);
|
||||||
|
chunked(client &, const http::code &);
|
||||||
|
chunked(const chunked &) = delete;
|
||||||
|
chunked(chunked &&) noexcept;
|
||||||
|
chunked() = default;
|
||||||
|
~chunked() noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
struct ircd::resource::method
|
struct ircd::resource::method
|
||||||
{
|
{
|
||||||
using handler = std::function<response (client &, request &)>;
|
using handler = std::function<response (client &, request &)>;
|
||||||
|
|
116
ircd/resource.cc
116
ircd/resource.cc
|
@ -451,6 +451,122 @@ catch(const std::bad_function_call &e)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// resource::response::chunked
|
||||||
|
//
|
||||||
|
|
||||||
|
ircd::resource::response::chunked::chunked(chunked &&other)
|
||||||
|
noexcept
|
||||||
|
:c{std::move(other.c)}
|
||||||
|
{
|
||||||
|
other.c = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::resource::response::chunked::chunked(client &client,
|
||||||
|
const http::code &code)
|
||||||
|
:chunked
|
||||||
|
{
|
||||||
|
client, code, "application/json; charset=utf-8"_sv, string_view{}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::resource::response::chunked::chunked(client &client,
|
||||||
|
const http::code &code,
|
||||||
|
const vector_view<const http::header> &headers)
|
||||||
|
:chunked
|
||||||
|
{
|
||||||
|
client, code, "application/json; charset=utf-8"_sv, headers
|
||||||
|
}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::resource::response::chunked::chunked(client &client,
|
||||||
|
const http::code &code,
|
||||||
|
const string_view &content_type,
|
||||||
|
const vector_view<const http::header> &headers)
|
||||||
|
:c{&client}
|
||||||
|
{
|
||||||
|
assert(!empty(content_type));
|
||||||
|
|
||||||
|
thread_local char buffer[4_KiB];
|
||||||
|
window_buffer sb{buffer};
|
||||||
|
{
|
||||||
|
const critical_assertion ca;
|
||||||
|
http::write(sb, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
response
|
||||||
|
{
|
||||||
|
client, code, content_type, size_t(-1), string_view{sb.completed()}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::resource::response::chunked::chunked(client &client,
|
||||||
|
const http::code &code,
|
||||||
|
const string_view &content_type,
|
||||||
|
const string_view &headers)
|
||||||
|
:c{&client}
|
||||||
|
{
|
||||||
|
response
|
||||||
|
{
|
||||||
|
client, code, content_type, size_t(-1), headers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ircd::resource::response::chunked::~chunked()
|
||||||
|
noexcept try
|
||||||
|
{
|
||||||
|
if(!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!std::uncaught_exceptions())
|
||||||
|
finish();
|
||||||
|
else
|
||||||
|
c->close(net::dc::RST, net::close_ignore);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::resource::response::chunked::finish()
|
||||||
|
{
|
||||||
|
if(!c)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
write(const_buffer{});
|
||||||
|
c = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
ircd::resource::response::chunked::write(const const_buffer &chunk)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
size_t ret{0};
|
||||||
|
|
||||||
|
if(!c)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
//TODO: bring iov from net::socket -> net::write_() -> client::write_()
|
||||||
|
char headbuf[32];
|
||||||
|
ret += c->write_all(http::writechunk(headbuf, size(chunk)));
|
||||||
|
ret += size(chunk)? c->write_all(chunk) : 0UL;
|
||||||
|
ret += c->write_all("\r\n"_sv);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
this->c = nullptr;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// resource::response
|
||||||
|
//
|
||||||
|
|
||||||
ircd::resource::response::response(client &client,
|
ircd::resource::response::response(client &client,
|
||||||
const http::code &code)
|
const http::code &code)
|
||||||
:response{client, json::object{json::empty_object}, code}
|
:response{client, json::object{json::empty_object}, code}
|
||||||
|
|
Loading…
Add table
Reference in a new issue