roar
Loading...
Searching...
No Matches
session.hpp
Go to the documentation of this file.
1#pragma once
2
4#include <functional>
5#include <roar/error.hpp>
7#include <roar/response.hpp>
17
18#include <boost/beast/http/message.hpp>
19#include <boost/beast/http/empty_body.hpp>
20#include <boost/beast/http/parser.hpp>
21#include <boost/beast/http/write.hpp>
22#include <boost/beast/http/read.hpp>
23#include <boost/beast/ssl/ssl_stream.hpp>
24#include <boost/beast/core/tcp_stream.hpp>
26#include <promise-cpp/promise.hpp>
27
28#include <memory>
29#include <optional>
30#include <chrono>
31#include <variant>
32#include <stdexcept>
33#include <sstream>
34
35namespace Roar
36{
37 class Router;
38 template <typename>
39 class Request;
40 class Session : public std::enable_shared_from_this<Session>
41 {
42 public:
43 friend class Route;
44 friend class Factory;
45
46 constexpr static uint64_t defaultHeaderLimit{8_MiB};
47 constexpr static uint64_t defaultBodyLimit{8_MiB};
48 constexpr static std::chrono::seconds sessionTimeout{10};
49
50 Session(
52 boost::beast::basic_flat_buffer<std::allocator<char>>&& buffer,
53 std::optional<std::variant<SslServerContext, boost::asio::ssl::context>>& sslContext,
54 bool isSecure,
55 std::function<void(Error&&)> onError,
56 std::weak_ptr<Router> router,
57 std::shared_ptr<const StandardResponseProvider> standardResponseProvider);
59
63 void close();
64
68 template <typename BodyT>
69 class SendIntermediate : public std::enable_shared_from_this<SendIntermediate<BodyT>>
70 {
71 public:
72 template <typename... Forwards, typename RequestBodyT>
73 SendIntermediate(Session& session, Request<RequestBodyT> const& req, Forwards&&... forwards)
74 : session_(session.shared_from_this())
75 , response_{session_->prepareResponse<BodyT>(req, std::forward<Forwards>(forwards)...)}
76 {}
77 SendIntermediate(Session& session, boost::beast::http::response<BodyT> res)
78 : session_(session.shared_from_this())
79 , response_{std::move(res)}
80 {}
82 : session_(session.shared_from_this())
83 , response_{std::move(res)}
84 {}
86 : session_(session.shared_from_this())
88 {}
93
99 SendIntermediate& status(boost::beast::http::status status)
100 {
101 response_.status(status);
102 return *this;
103 }
104
110 auto& body()
111 {
112 return response_.body();
113 }
114
122 template <typename T>
123 SendIntermediate& body(T&& toAssign)
124 {
125 response_.body(std::forward<T>(toAssign));
127 return *this;
128 }
129
136 SendIntermediate& chunked(bool activate = true)
137 {
138 response_.chunked(activate);
139 return *this;
140 }
141
148 template <typename T>
150 {
151 response_.contentType(std::forward<T>(type));
152 return *this;
153 }
154
160 template <typename T>
161 SendIntermediate& setHeader(boost::beast::http::field field, T&& value)
162 {
163 response_.setHeader(field, std::forward<T>(value));
164 return *this;
165 }
166 template <typename T>
167 SendIntermediate& header(boost::beast::http::field field, T&& value)
168 {
169 return setHeader(field, std::forward<T>(value));
170 }
171
179 SendIntermediate& onWriteSome(std::function<bool(std::size_t)> onChunkFunc)
180 {
181 onChunk_ = onChunkFunc;
182 return *this;
183 }
184
192 template <typename RequestBodyT2>
194 enableCors(Request<RequestBodyT2> const& req, std::optional<CorsSettings> cors = std::nullopt)
195 {
196 response_.enableCors(req, std::move(cors));
197 return *this;
198 }
199
201 {
202 response_.preparePayload();
203 return *this;
204 }
205
207 {
208 func(response_);
209 return *this;
210 }
211
212 private:
215
216 public:
220 template <typename T = BodyT, bool OverrideSfinae = false>
221 std::enable_if_t<
222 !(std::is_same_v<T, RangeFileBody> || std::is_same_v<T, boost::beast::http::empty_body>) ||
223 OverrideSfinae,
226 {
227 if (overallTimeout_)
228 {
229 session_->withStreamDo([this](auto& stream) {
230 boost::beast::get_lowest_layer(stream).expires_after(*overallTimeout_);
231 });
232 }
233 promise_ = std::make_unique<promise::Promise>(promise::newPromise());
234 serializer_ = std::make_unique<boost::beast::http::serializer<false, BodyT>>(response_.response());
235 writeChunk();
236 return {*promise_};
237 }
238
242 template <typename T = BodyT>
243 std::enable_if_t<std::is_same_v<T, boost::beast::http::empty_body>, CommitReturnType> commit()
244 {
245 if (overallTimeout_)
246 {
247 session_->withStreamDo([this](auto& stream) {
248 boost::beast::get_lowest_layer(stream).expires_after(*overallTimeout_);
249 });
250 }
251 promise_ = std::make_unique<promise::Promise>(promise::newPromise());
252 serializer_ = std::make_unique<boost::beast::http::serializer<false, BodyT>>(response_.response());
253 writeHeader();
254 return {*promise_};
255 }
256
260 template <typename T = BodyT>
261 std::enable_if_t<std::is_same_v<T, RangeFileBody>, CommitReturnType> commit()
262 {
263 using namespace boost::beast::http;
265 if (response_.body().isMultipart())
266 setHeader(field::content_type, "multipart/byteranges; boundary=" + response_.body().boundary());
267 else
268 {
269 const auto first = response_.body().firstRange().first;
270 const auto second = response_.body().firstRange().second;
271 const auto fileSize = response_.body().fileSize();
272
273 setHeader(
274 field::content_range,
275 std::string{"bytes "} + std::to_string(first) + "-" + std::to_string(second) + "/" +
276 std::to_string(fileSize));
277 }
278 status(status::partial_content);
279 return commit<BodyT, true>();
280 }
281
287 SendIntermediate& rejectAuthorization(std::string const& wwwAuthenticate)
288 {
289 if (!wwwAuthenticate.empty())
290 response_.setHeader(boost::beast::http::field::www_authenticate, wwwAuthenticate);
291 response_.status(boost::beast::http::status::unauthorized);
292 return *this;
293 }
294
302 {
303 response_.keepAlive(keepAlive);
304 return *this;
305 }
306
314 {
315 response_.setCookie(cookie);
316 return *this;
317 }
318
325 SendIntermediate& useFixedTimeout(std::chrono::milliseconds timeout)
326 {
327 overallTimeout_ = timeout;
328 return *this;
329 }
330
331 private:
333 {
334 session_->withStreamDo([this](auto& stream) {
335 if (!overallTimeout_)
336 boost::beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(sessionTimeout));
337
338 boost::beast::http::async_write_header(
339 stream,
341 [self = this->shared_from_this()](boost::beast::error_code ec, std::size_t) {
342 if (ec)
343 self->promise_->fail(ec);
344 else
345 self->promise_->resolve(false);
346 });
347 });
348 }
349
351 {
352 session_->withStreamDo([this](auto& stream) {
353 if (!overallTimeout_)
354 boost::beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(sessionTimeout));
355
356 boost::beast::http::async_write_some(
357 stream,
359 [self = this->shared_from_this()](boost::beast::error_code ec, std::size_t bytesTransferred) {
360 if (!ec && !self->serializer_->is_done())
361 return self->writeChunk();
362
363 if (ec)
364 {
365 self->session_->close();
366 self->promise_->reject(Error{.error = ec, .additionalInfo = "Failed to send response"});
367 return;
368 }
369
370 if (self->onChunk_ && !self->onChunk_(bytesTransferred))
371 return;
372
373 try
374 {
375 self->promise_->resolve(self->session_->onWriteComplete(
376 self->serializer_->get().need_eof(), ec, bytesTransferred));
377 }
378 catch (std::exception const& exc)
379 {
380 self->promise_->fail(
381 Error{.error = exc.what(), .additionalInfo = "Failed to send response"});
382 }
383 });
384 });
385 }
386
387 private:
388 std::shared_ptr<Session> session_;
390 std::function<bool(std::size_t)> onChunk_;
391 std::unique_ptr<promise::Promise> promise_;
392 std::optional<std::chrono::milliseconds> overallTimeout_;
393 std::unique_ptr<boost::beast::http::serializer<false, BodyT>> serializer_;
394 };
395
396 template <typename BodyT, typename OriginalBodyT, typename... Forwards>
397 [[nodiscard]] std::shared_ptr<SendIntermediate<BodyT>>
398 send(Request<OriginalBodyT> const& req, Forwards&&... forwards)
399 {
400 return std::shared_ptr<SendIntermediate<BodyT>>(
401 new SendIntermediate<BodyT>{*this, req, std::forward<Forwards>(forwards)...});
402 }
403
404 template <typename BodyT>
405 [[nodiscard]] std::shared_ptr<SendIntermediate<BodyT>> send(boost::beast::http::response<BodyT>&& res)
406 {
407 return std::shared_ptr<SendIntermediate<BodyT>>(new SendIntermediate<BodyT>{*this, std::move(res)});
408 }
409
410 template <typename BodyT>
411 [[nodiscard]] std::shared_ptr<SendIntermediate<BodyT>> send(Response<BodyT>&& res)
412 {
413 return std::shared_ptr<SendIntermediate<BodyT>>(new SendIntermediate<BodyT>{*this, std::move(res)});
414 }
415
416 template <typename BodyT>
417 [[nodiscard]] std::shared_ptr<SendIntermediate<BodyT>> sendWithAllAcceptedCors()
418 {
419 return std::shared_ptr<SendIntermediate<BodyT>>(new SendIntermediate<BodyT>{*this});
420 }
421
428 send(std::string message, std::chrono::seconds timeout = std::chrono::seconds{10});
429
435 template <typename BodyT>
436 class ReadIntermediate : public std::enable_shared_from_this<ReadIntermediate<BodyT>>
437 {
438 private:
439 friend Session;
440
441 template <typename OriginalBodyT, typename... Forwards>
442 ReadIntermediate(Session& session, Request<OriginalBodyT> req, Forwards&&... forwardArgs)
443 : session_{session.shared_from_this()}
444 , req_{[&session, &forwardArgs...]() -> decltype(req_) {
445 if constexpr (std::is_same_v<BodyT, boost::beast::http::empty_body>)
446 throw std::runtime_error("Attempting to read with empty_body type.");
447 else
448 return boost::beast::http::request_parser<BodyT>{
449 std::move(*session.parser()), std::forward<Forwards>(forwardArgs)...};
450 session.parser().reset();
451 }()}
452 , originalExtensions_{std::move(req).ejectExtensions()}
453 , onChunk_{}
454 , promise_{}
455 , overallTimeout_{std::nullopt}
456 {
457 req_.body_limit(defaultBodyLimit);
458 }
459
460 public:
463
470 ReadIntermediate& bodyLimit(std::size_t limit)
471 {
472 req_.body_limit(limit);
473 return *this;
474 }
475
482 ReadIntermediate& bodyLimit(boost::beast::string_view limit)
483 {
484 req_.body_limit(std::stoull(std::string{limit}));
485 return *this;
486 }
487
494 {
495 req_.body_limit(boost::none);
496 return *this;
497 }
498
506 ReadIntermediate& onReadSome(std::function<bool(boost::beast::flat_buffer&, std::size_t)> onChunkFunc)
507 {
508 onChunk_ = onChunkFunc;
509 return *this;
510 }
511
524 {
525 if (overallTimeout_)
526 {
527 session_->withStreamDo([this](auto& stream) {
528 boost::beast::get_lowest_layer(stream).expires_after(*overallTimeout_);
529 });
530 }
531 promise_ = std::make_unique<promise::Promise>(promise::newPromise());
532 readChunk();
533 return {*promise_};
534 }
535
542 ReadIntermediate& useFixedTimeout(std::chrono::milliseconds timeout)
543 {
544 overallTimeout_ = timeout;
545 return *this;
546 }
547
548 private:
553 {
554 session_->withStreamDo([this](auto& stream) {
555 if (!overallTimeout_)
556 boost::beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(sessionTimeout));
557 boost::beast::http::async_read_some(
558 stream,
559 session_->buffer(),
560 req_,
561 [self = this->shared_from_this()](boost::beast::error_code ec, std::size_t bytesReceived) {
562 if (!ec && !self->req_.is_done())
563 return self->readChunk();
564
565 if (ec)
566 {
567 self->session_->close();
568 self->promise_->reject(Error{.error = ec});
569 }
570
571 if (self->onChunk_ && !self->onChunk_(self->session_->buffer(), bytesReceived))
572 return;
573
574 auto request = Request<BodyT>(self->req_.release(), std::move(self->originalExtensions_));
575 try
576 {
577 self->promise_->template resolve(Detail::ref(*self->session_), Detail::cref(request));
578 }
579 catch (std::exception const& exc)
580 {
581 using namespace std::string_literals;
582 self->session_
583 ->send(self->session_->standardResponseProvider().makeStandardResponse(
584 *self->session_,
585 boost::beast::http::status::internal_server_error,
586 "An exception was thrown in the body read completion handler: "s + exc.what()))
587 ->commit();
588 }
589 });
590 });
591 }
592
593 private:
594 std::shared_ptr<Session> session_;
595 boost::beast::http::request_parser<BodyT> req_;
597 std::function<bool(boost::beast::flat_buffer&, std::size_t)> onChunk_;
598 std::unique_ptr<promise::Promise> promise_;
599 std::optional<std::chrono::milliseconds> overallTimeout_;
600 };
601
607 void readLimit(std::size_t bytesPerSecond);
608
614 void writeLimit(std::size_t bytesPerSecond);
615
627 template <typename BodyT, typename OriginalBodyT, typename... Forwards>
628 [[nodiscard]] std::shared_ptr<ReadIntermediate<BodyT>>
629 read(Request<OriginalBodyT> req, Forwards&&... forwardArgs)
630 {
631 return std::shared_ptr<ReadIntermediate<BodyT>>(
632 new ReadIntermediate<BodyT>{*this, std::move(req), std::forward<Forwards>(forwardArgs)...});
633 }
634
641 template <typename BodyT = boost::beast::http::empty_body, typename RequestBodyT, typename... Forwards>
642 [[nodiscard]] Response<BodyT> prepareResponse(Request<RequestBodyT> const& req, Forwards&&... forwardArgs)
643 {
644 auto res = Response<BodyT>{std::forward<Forwards>(forwardArgs)...};
645 res.setHeader(boost::beast::http::field::server, "Roar+" BOOST_BEAST_VERSION_STRING);
646 if (routeOptions().cors)
647 res.enableCors(req, routeOptions().cors);
648 return res;
649 }
650 template <typename BodyT = boost::beast::http::empty_body>
652 {
653 auto res = Response<BodyT>{};
654 res.setHeader(boost::beast::http::field::server, "Roar+" BOOST_BEAST_VERSION_STRING);
655 if (routeOptions().cors)
657 return res;
658 }
659
666 template <typename FunctionT>
667 void withStreamDo(FunctionT&& func)
668 {
669 std::visit(std::forward<FunctionT>(func), stream());
670 }
671
679 [[nodiscard]] Detail::PromiseTypeBind<
682 upgrade(Request<boost::beast::http::empty_body> const& req);
683
689 [[nodiscard]] RouteOptions const& routeOptions();
690
697 bool isSecure() const;
698
705 void sendStandardResponse(boost::beast::http::status status, std::string_view additionalInfo = "");
706
710 void sendStrictTransportSecurityResponse();
711
719 template <typename OriginalBodyT>
721 awaitClientClose(Request<OriginalBodyT> req, std::chrono::milliseconds timeout = std::chrono::seconds{3})
722 {
723 return promise::newPromise([this, &req, &timeout](promise::Defer d) {
724 read<VoidBody>(std::move(req))
725 ->useFixedTimeout(timeout)
726 .commit()
727 .then([d](auto&, auto const&) {
728 d.resolve();
729 })
730 .fail([d](Error const& e) {
731 d.reject(e);
732 });
733 });
734 }
735
736 private:
737 void setupRouteOptions(RouteOptions options);
738
739 private:
740 void readHeader();
741 void performSslHandshake();
742 bool onWriteComplete(bool expectsClose, boost::beast::error_code ec, std::size_t);
743 std::variant<Detail::StreamType, boost::beast::ssl_stream<Detail::StreamType>>& stream();
744 std::shared_ptr<boost::beast::http::request_parser<boost::beast::http::empty_body>>& parser();
745 boost::beast::flat_buffer& buffer();
746 StandardResponseProvider const& standardResponseProvider();
747 void startup(bool immediate = true);
748
749 private:
750 struct Implementation;
751 std::unique_ptr<Implementation> impl_;
752 };
753}
Definition cookie.hpp:18
This factory creates sessions.
Definition factory.hpp:23
This class extends the boost::beast::http::request<BodyT> with additional convenience.
Definition request.hpp:52
Definition response.hpp:29
Response & enableCors(Request< RequestBodyT > const &req, std::optional< CorsSettings > cors=std::nullopt)
Sets cors headers.
Definition response.hpp:326
Response & setHeader(boost::beast::http::field field, std::string const &value)
Can be used to set a header field.
Definition response.hpp:269
Response & enableCorsEverything()
Definition response.hpp:378
A route represents the mapping of a verb+path to a user provided function.
Definition route.hpp:21
Utility class to build up read operations.
Definition session.hpp:437
Detail::RequestExtensions originalExtensions_
Definition session.hpp:596
boost::beast::http::request_parser< BodyT > req_
Definition session.hpp:595
friend Session
Definition session.hpp:439
ReadIntermediate & noBodyLimit()
Accept a body of any length.
Definition session.hpp:493
ReadIntermediate(ReadIntermediate &&)=default
ReadIntermediate & bodyLimit(std::size_t limit)
Set a body limit.
Definition session.hpp:470
void readChunk()
Reads some bytes off of the stream.
Definition session.hpp:552
ReadIntermediate & onReadSome(std::function< bool(boost::beast::flat_buffer &, std::size_t)> onChunkFunc)
Set a callback function that is called whenever some data was read.
Definition session.hpp:506
std::optional< std::chrono::milliseconds > overallTimeout_
Definition session.hpp:599
ReadIntermediate & operator=(ReadIntermediate &&)=default
std::unique_ptr< promise::Promise > promise_
Definition session.hpp:598
ReadIntermediate & bodyLimit(boost::beast::string_view limit)
Set a body limit.
Definition session.hpp:482
ReadIntermediate & useFixedTimeout(std::chrono::milliseconds timeout)
Set a timeout for the whole read operation.
Definition session.hpp:542
std::function< bool(boost::beast::flat_buffer &, std::size_t)> onChunk_
Definition session.hpp:597
Detail::PromiseTypeBind< Detail::PromiseTypeBindThen< Detail::PromiseReferenceWrap< Session >, Detail::PromiseReferenceWrap< Request< BodyT > const > >, Detail::PromiseTypeBindFail< Error const & > > commit()
Start reading here. If you dont call this function, nothing is read.
Definition session.hpp:523
ReadIntermediate(Session &session, Request< OriginalBodyT > req, Forwards &&... forwardArgs)
Definition session.hpp:442
std::shared_ptr< Session > session_
Definition session.hpp:594
Helper class to prepare and send a response.
Definition session.hpp:70
SendIntermediate & modifyResponse(std::function< void(Response< BodyT > &)> func)
Definition session.hpp:206
SendIntermediate(Session &session, Response< BodyT > &&res)
Definition session.hpp:81
SendIntermediate & header(boost::beast::http::field field, T &&value)
Definition session.hpp:167
SendIntermediate & useFixedTimeout(std::chrono::milliseconds timeout)
Set a timeout for the whole write operation.
Definition session.hpp:325
SendIntermediate & body(T &&toAssign)
This function can be used to assign something to the body.
Definition session.hpp:123
SendIntermediate & rejectAuthorization(std::string const &wwwAuthenticate)
Sets WWW-Authenticate header and sets the status to unauthorized.
Definition session.hpp:287
std::enable_if_t< std::is_same_v< T, boost::beast::http::empty_body >, CommitReturnType > commit()
Sends the response and invalidates this object.
Definition session.hpp:243
std::unique_ptr< boost::beast::http::serializer< false, BodyT > > serializer_
Definition session.hpp:393
SendIntermediate & operator=(SendIntermediate &&)=default
std::optional< std::chrono::milliseconds > overallTimeout_
Definition session.hpp:392
SendIntermediate & setCookie(Cookie const &cookie)
Sets a cookie.
Definition session.hpp:313
std::enable_if_t< std::is_same_v< T, RangeFileBody >, CommitReturnType > commit()
Sends the response for range request file bodies. Sets appropriate headers.
Definition session.hpp:261
std::function< bool(std::size_t)> onChunk_
Definition session.hpp:390
SendIntermediate & setHeader(boost::beast::http::field field, T &&value)
Can be used to set a header field.
Definition session.hpp:161
SendIntermediate(Session &session)
Definition session.hpp:85
std::shared_ptr< Session > session_
Definition session.hpp:388
std::enable_if_t< !(std::is_same_v< T, RangeFileBody >||std::is_same_v< T, boost::beast::http::empty_body >)||OverrideSfinae, CommitReturnType > commit()
Sends the response and invalidates this object.
Definition session.hpp:225
SendIntermediate(SendIntermediate const &)=delete
SendIntermediate & chunked(bool activate=true)
(De)Activate chunked encoding.
Definition session.hpp:136
SendIntermediate(SendIntermediate &&)=default
SendIntermediate & preparePayload()
Definition session.hpp:200
SendIntermediate & keepAlive(bool keepAlive=true)
Set keep alive.
Definition session.hpp:301
void writeChunk()
Definition session.hpp:350
Response< BodyT > response_
Definition session.hpp:389
std::unique_ptr< promise::Promise > promise_
Definition session.hpp:391
SendIntermediate(Session &session, Request< RequestBodyT > const &req, Forwards &&... forwards)
Definition session.hpp:73
SendIntermediate & onWriteSome(std::function< bool(std::size_t)> onChunkFunc)
Set a callback function that is called whenever some data was written.
Definition session.hpp:179
SendIntermediate & operator=(SendIntermediate const &)=delete
SendIntermediate & enableCors(Request< RequestBodyT2 > const &req, std::optional< CorsSettings > cors=std::nullopt)
Sets cors headers.
Definition session.hpp:194
SendIntermediate & status(boost::beast::http::status status)
Sets the response status code.
Definition session.hpp:99
SendIntermediate(Session &session, boost::beast::http::response< BodyT > res)
Definition session.hpp:77
SendIntermediate & contentType(T &&type)
For setting of the content type.
Definition session.hpp:149
auto & body()
Retrieve the response body object.
Definition session.hpp:110
void writeHeader()
Definition session.hpp:332
Definition session.hpp:41
Response< BodyT > prepareResponse()
Definition session.hpp:651
std::variant< Detail::StreamType, boost::beast::ssl_stream< Detail::StreamType > > & stream()
Definition session.cpp:260
std::shared_ptr< boost::beast::http::request_parser< boost::beast::http::empty_body > > & parser()
Definition session.cpp:265
std::shared_ptr< SendIntermediate< BodyT > > send(Response< BodyT > &&res)
Definition session.hpp:411
std::shared_ptr< SendIntermediate< BodyT > > send(boost::beast::http::response< BodyT > &&res)
Definition session.hpp:405
std::unique_ptr< Implementation > impl_
Definition session.hpp:751
static constexpr uint64_t defaultBodyLimit
Definition session.hpp:47
std::shared_ptr< SendIntermediate< BodyT > > send(Request< OriginalBodyT > const &req, Forwards &&... forwards)
Definition session.hpp:398
StandardResponseProvider const & standardResponseProvider()
Definition session.cpp:275
Detail::PromiseTypeBind< Detail::PromiseTypeBindThen<>, Detail::PromiseTypeBindFail< Error const & > > awaitClientClose(Request< OriginalBodyT > req, std::chrono::milliseconds timeout=std::chrono::seconds{3})
Some clients insist on closing the connection on their own even if they received a response....
Definition session.hpp:721
ROAR_PIMPL_SPECIAL_FUNCTIONS(Session)
Response< BodyT > prepareResponse(Request< RequestBodyT > const &req, Forwards &&... forwardArgs)
Prepares a response with some header values already set.
Definition session.hpp:642
std::shared_ptr< ReadIntermediate< BodyT > > read(Request< OriginalBodyT > req, Forwards &&... forwardArgs)
Read data from the client.
Definition session.hpp:629
void withStreamDo(FunctionT &&func)
std::visit for the underlying beast stream. Either ssl_stream or tcp_stream.
Definition session.hpp:667
boost::beast::flat_buffer & buffer()
Definition session.cpp:270
bool isSecure() const
Returns whether or not this is an encrypted session.
Definition session.cpp:230
static constexpr uint64_t defaultHeaderLimit
Definition session.hpp:46
void close()
Calls shutdown on the socket.
Definition session.cpp:306
static constexpr std::chrono::seconds sessionTimeout
Definition session.hpp:48
std::shared_ptr< SendIntermediate< BodyT > > sendWithAllAcceptedCors()
Definition session.hpp:417
Definition forward.hpp:11
Definition forward.hpp:29
auto ref(T &thing)
Definition promise_compat.hpp:20
auto cref(T const &thing)
Definition promise_compat.hpp:26
Definition authorization.hpp:10
Definition promise_compat.hpp:10
Definition promise_compat.hpp:67
Definition promise_compat.hpp:63
Definition promise_compat.hpp:70
Definition request.hpp:34
Holds errors that are produced asynchronously anywhere.
Definition error.hpp:20
std::variant< boost::system::error_code, std::string > error
Definition error.hpp:21
Options that modify the server behavior for a given route.
Definition proto_route.hpp:18