4#include "Stroika/Frameworks/StroikaPreComp.h"
15#include "Stroika/Foundation/Containers/Common.h"
16#include "Stroika/Foundation/Containers/Support/ReserveTweaks.h"
17#include "Stroika/Foundation/DataExchange/BadFormatException.h"
24#include "Stroika/Foundation/IO/Network/HTTP/ClientErrorException.h"
25#include "Stroika/Foundation/IO/Network/HTTP/Exception.h"
26#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
36using namespace Stroika::Foundation::Memory;
38using namespace Stroika::Frameworks;
42using PropertyChangedEventResultType = Common::PropertyCommon::PropertyChangedEventResultType;
62 constexpr bool kTransferEncodingCompressionDoesntAppearToWorkWithBrowsers_ =
true;
66 constexpr char kCRLF_[] =
"\r\n";
69static_assert (not copyable<Response>);
70static_assert (movable<Response>);
72Response::Response (Response&& src)
74 : Response{src.fSocket_, src.fProtocolOutputStream_, src.headers ()}
76 fState_ = src.fState_;
77 fHeadMode_ = src.fHeadMode_;
78 fAborted_ = src.fAborted_;
79 fAutoTransferChunkSize_ = src.fAutoTransferChunkSize_;
80 fBodyEncoding_ = move (src.fBodyEncoding_);
81 fBodyRawStream_ = move (src.fBodyRawStream_);
82 fBodyRawStreamLength_ = move (src.fBodyRawStreamLength_);
83 fBodyRowStreamLengthWhenLastChunkGenerated_ = move (src.fBodyRowStreamLengthWhenLastChunkGenerated_);
84 fBodyCompressedStream_ = move (src.fBodyCompressedStream_);
85 fUseOutStream_ = move (src.fUseOutStream_);
86 fCodePage_ = move (src.fCodePage_);
87 fCodeCvt_ = move (src.fCodeCvt_);
88 fETagDigester_ = move (src.fETagDigester_);
92 : inherited{initialHeaders}
93 , autoComputeETag{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]] const auto* property) {
94 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::autoComputeETag);
96 return thisObj->fETagDigester_.has_value ();
98 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
auto* property,
const bool newAutoComputeETag) {
99 Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::autoComputeETag);
101 Require (thisObj->state () == State::ePreparingHeaders);
102 Require (thisObj->fBodyRawStreamLength_ == 0);
103 if (newAutoComputeETag) {
104 thisObj->fETagDigester_ = ETagDigester_{};
107 thisObj->fETagDigester_ = nullopt;
110 , automaticTransferChunkSize{
111 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
112 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::automaticTransferChunkSize);
114 return thisObj->fAutoTransferChunkSize_;
116 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
auto* property,
const optional<size_t>& newAutoComputeValue) {
117 Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::automaticTransferChunkSize);
119 Require (thisObj->state () == State::ePreparingHeaders);
120 thisObj->fAutoTransferChunkSize_ = newAutoComputeValue;
122 , bodyEncoding{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
123 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::bodyEncoding);
125 return thisObj->fBodyEncoding_;
127 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
auto* property,
const auto& newCT) {
128 Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::bodyEncoding);
130 thisObj->fBodyEncoding_ = newCT;
132 , chunkedTransferMode{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
133 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::chunkedTransferMode);
135 auto te = thisObj->headers ().transferEncoding ();
138 , codeCvt{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
139 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::codeCvt);
141 if (thisObj->fCodeCvt_ == nullopt) {
146 return *thisObj->fCodeCvt_;
148 , codePage{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
149 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::codePage);
151 return thisObj->fCodePage_;
153 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
auto* property,
const auto& newCodePage) {
154 Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::codePage);
156 Require (thisObj->headersCanBeSet ());
157 Require (thisObj->fBodyRawStreamLength_ == 0);
158 bool diff = thisObj->fCodePage_ != newCodePage;
159 thisObj->fCodePage_ = newCodePage;
161 if (
auto ct = thisObj->headers ().contentType ()) {
162 thisObj->rwHeaders ().contentType = thisObj->AdjustContentTypeForCodePageIfNeeded_ (*ct);
164 thisObj->fCodeCvt_ = nullopt;
167 , contentType{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
168 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::contentType);
170 return thisObj->headers ().contentType ();
172 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
auto* property,
const auto& newCT) {
173 Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::contentType);
175 thisObj->rwHeaders ().contentType = newCT;
177 , hasEntityBody{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
178 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::hasEntityBody);
180 if (thisObj->fHeadMode_) {
183 if (thisObj->status () == HTTP::StatusCodes::kNotModified) {
186 return thisObj->fBodyRawStreamLength_ > 0;
188 , headersCanBeSet{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
189 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::headersCanBeSet);
191 return thisObj->fState_ == State::ePreparingHeaders;
193 , headMode{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
194 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::headMode);
196 return thisObj->fHeadMode_;
198 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
auto* property,
const auto& newHeadMode) {
199 Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::headMode);
201 Require (thisObj->fState_ == State::ePreparingHeaders);
203 thisObj->fHeadMode_ =
true;
206 Require (thisObj->fHeadMode_ == newHeadMode);
209 , location{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
210 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::location);
212 return thisObj->headers ().location ();
214 [qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
auto* property,
const auto& newLoc) {
215 Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::location);
217 thisObj->rwHeaders ().location = newLoc;
219 , responseAborted{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
220 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::responseAborted);
222 return thisObj->fAborted_;
224 , responseCompleted{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
225 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::responseCompleted);
227 return thisObj->fState_ == State::eCompleted;
229 , responseStatusSent{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
230 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::responseStatusSent);
232 return thisObj->fState_ != State::ePreparingHeaders;
234 , state{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]]
const auto* property) {
235 const Response* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Response::state);
237 return thisObj->fState_;
240 , fProtocolOutputStream_{outStream}
242 .
fInternallySynchronized = Execution::InternallySynchronized::eNotKnownInternallySynchronized, .fSeekable =
false})}
243 , fUseOutStream_{Streams::BufferedOutputStream::New<byte> (outStream)}
246 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wunused-lambda-capture\"");
247 this->status.rwPropertyChangedHandlers ().push_front ([
this] ([[maybe_unused]]
const auto& propertyChangedEvent) {
248 Require (not this->responseStatusSent ());
249 return PropertyChangedEventResultType::eContinueProcessing;
251 this->statusAndOverrideReason.rwPropertyChangedHandlers ().push_front ([
this] ([[maybe_unused]]
const auto& propertyChangedEvent) {
252 Require (not this->responseStatusSent ());
253 return PropertyChangedEventResultType::eContinueProcessing;
255 this->rwHeaders.rwPropertyReadHandlers ().push_front ([
this] (
HTTP::Headers* h) {
256 Require (this->headersCanBeSet ());
259 this->rwHeaders.rwPropertyChangedHandlers ().push_front ([
this] ([[maybe_unused]]
const auto& propertyChangedEvent) {
260 Require (this->headersCanBeSet ());
261 return PropertyChangedEventResultType::eContinueProcessing;
263 DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wunused-lambda-capture\"");
265 this->rwHeaders ().transferEncoding.rwPropertyChangedHandlers ().push_front ([
this] ([[maybe_unused]]
const auto& propertyChangedEvent) {
267 Require (this->headersCanBeSet ());
268 return PropertyChangedEventResultType::eContinueProcessing;
271 this->rwHeaders ().contentLength.rwPropertyReadHandlers ().push_front ([
this] ([[maybe_unused]]
const auto& baseValue) -> optional<uint64_t> {
272 if (this->chunkedTransferMode ()) {
275 if (this->fHeadMode_) {
284 if (fBodyCompressedStream_ !=
nullptr) {
285 return fBodyCompressedStream_.GetOffset ();
287 if (this->fBodyRawStream_ !=
nullptr) {
288 return fBodyRawStreamLength_;
293 this->rwHeaders ().contentLength.rwPropertyChangedHandlers ().push_front ([] ([[maybe_unused]]
const auto& propertyChangedEvent) {
295 return PropertyChangedEventResultType::eSilentlyCutOffProcessing;
298 this->rwHeaders ().ETag.rwPropertyReadHandlers ().push_front ([
this] (
const auto& baseETagValue) -> optional<HTTP::ETag> {
300 if (fETagDigester_) {
301 auto copy = *fETagDigester_;
304 return baseETagValue;
306 this->rwHeaders ().ETag.rwPropertyChangedHandlers ().push_front ([
this] ([[maybe_unused]]
const auto& propertyChangedEvent) {
307 Require (this->headersCanBeSet ());
310 this->autoComputeETag =
false;
311 return PropertyChangedEventResultType::eContinueProcessing;
315Response& Response::operator= (Response&& rhs)
noexcept
317 inherited::operator= (move (rhs));
318 fSocket_ = rhs.fSocket_;
319 fProtocolOutputStream_ = rhs.fProtocolOutputStream_;
320 fState_ = rhs.fState_;
321 fHeadMode_ = rhs.fHeadMode_;
322 fAborted_ = rhs.fAborted_;
323 fAutoTransferChunkSize_ = rhs.fAutoTransferChunkSize_;
324 fBodyEncoding_ = move (rhs.fBodyEncoding_);
325 fBodyRawStream_ = move (rhs.fBodyRawStream_);
326 fBodyRawStreamLength_ = move (rhs.fBodyRawStreamLength_);
327 fBodyRowStreamLengthWhenLastChunkGenerated_ = move (rhs.fBodyRowStreamLengthWhenLastChunkGenerated_);
328 fBodyCompressedStream_ = move (rhs.fBodyCompressedStream_);
329 fUseOutStream_ = move (rhs.fUseOutStream_);
330 fCodePage_ = move (rhs.fCodePage_);
331 fCodeCvt_ = move (rhs.fCodeCvt_);
332 fETagDigester_ = move (rhs.fETagDigester_);
336void Response::StateTransition_ (State to)
338#if USE_NOISY_TRACE_IN_THIS_MODULE_
339 Debug::TraceContextBumper ctx{
"Response::StateTransition_",
"from={}, to={}"_f,
static_cast<State
> (fState_),
static_cast<State
> (to)};
341 Require (fState_ <= to);
343 if (fState_ == State::ePreparingHeaders and to == State::eHeadersSent) {
344 ApplyBodyEncodingIfNeeded_ ();
346 auto curStatusInfo = this->statusAndOverrideReason ();
347 Status curStatus = get<0> (curStatusInfo);
349 Memory::NullCoalesce (get<1> (curStatusInfo), IO::Network::HTTP::Exception::GetStandardTextForStatus (curStatus,
true));
350 wstring version = L
"1.1";
351 String tmp =
"HTTP/{} {} {}\r\n"_f(version, curStatus, statusMsg);
352 u8string utf8 = tmp.
AsUTF8 ();
353 fUseOutStream_.Write (as_bytes (span{utf8.data (), utf8.length ()}));
356 for (
const auto& i : this->headers ().As<> ()) {
357 u8string utf8 =
"{}: {}\r\n"_f(i.fKey, i.fValue).AsUTF8 ();
358 fUseOutStream_.Write (as_bytes (span{utf8.data (), utf8.length ()}));
360#if USE_NOISY_TRACE_IN_THIS_MODULE_
361 DbgTrace (
"headers: {}"_f, headers ());
364 fUseOutStream_.Write (as_bytes (span{kCRLF_, ::strlen (kCRLF_)}));
368 if (to >= State::eHeadersSent and hasEntityBody ()) {
369 Assert (chunkedTransferMode () or this->headers ().contentLength ().has_value ());
375void Response::ApplyBodyEncodingIfNeeded_ ()
377#if USE_NOISY_TRACE_IN_THIS_MODULE_
380 if (fState_ == State::ePreparingHeaders and fBodyEncoding_ and fBodyCompressedStream_ ==
nullptr) {
382 if (this->chunkedTransferMode ()) {
383 if (kTransferEncodingCompressionDoesntAppearToWorkWithBrowsers_) {
384 rwHeaders ().contentEncoding = ce;
387 HTTP::TransferEncodings htc = *headers ().transferEncoding ();
389 rwHeaders ().transferEncoding = htc;
393 rwHeaders ().contentEncoding = ce;
396 Compression::Ptr currentCompression;
397 if constexpr (Compression::Deflate::kSupported) {
399 constexpr auto compressOpts = Compression::Deflate::Compress::Options{.fCompressionLevel = 1.0f};
400 currentCompression = Compression::Deflate::Compress::New (compressOpts);
404 if constexpr (Compression::GZip::kSupported) {
406 static const auto compressOpts = Compression::GZip::Compress::Options{{.fCompressionLevel = 1.0f}};
407 currentCompression = Compression::GZip::Compress::New (compressOpts);
411 if (currentCompression) {
413 fBodyCompressedStream_ = currentCompression.Transform (fBodyRawStream_);
418void Response::WriteChunk_ (span<const byte> rawBytes)
420#if USE_NOISY_TRACE_IN_THIS_MODULE_
424 string n = CString::Format (
"%x\r\n",
static_cast<unsigned int> (rawBytes.size ()));
425 fUseOutStream_.Write (as_bytes (span{n.data (), n.size ()}));
426 fUseOutStream_.Write (rawBytes);
427 fUseOutStream_.Write (as_bytes (span{kCRLF_, strlen (kCRLF_)}));
436 params.
Add (
"charset"sv, Characters::GetCharsetString (fCodePage_), AddReplaceMode::eAddIfMissing);
442void Response::Flush ()
444#if USE_NOISY_TRACE_IN_THIS_MODULE_
449 if (fState_ == State::ePreparingHeaders) {
450 StateTransition_ (State::eHeadersSent);
452 Assert (fState_ >= State::eHeadersSent);
453 fUseOutStream_.Flush ();
458#if USE_NOISY_TRACE_IN_THIS_MODULE_
463 if (fState_ != State::eCompleted) {
465 fBodyRawStream_.CloseWrite ();
467 ApplyBodyEncodingIfNeeded_ ();
472 optional<BLOB> body2Write;
473 if (not chunkedTransferMode ()) {
474 if (fBodyCompressedStream_ !=
nullptr) {
475 body2Write = fBodyCompressedStream_.ReadAll ();
478 body2Write = fBodyRawStream_.ReadAll ();
481 if (fState_ == State::ePreparingHeaders) {
482 StateTransition_ (State::eHeadersSent);
484 Assert (fState_ >= State::eHeadersSent);
486 if (chunkedTransferMode () and not fHeadMode_) {
487 if (fBodyCompressedStream_ !=
nullptr) {
488 auto b = fBodyCompressedStream_.ReadAll ();
489 if (not b.empty ()) {
494 auto b = fBodyRawStream_.ReadAll ();
495 if (not b.empty ()) {
499 WriteChunk_ (span<const byte>{});
502 if (fState_ == State::ePreparingHeaders) {
503 StateTransition_ (State::eHeadersSent);
506 Assert (not chunkedTransferMode ());
507 Assert (fState_ != State::eCompleted);
509 if (this->hasEntityBody ()) {
510 fUseOutStream_.Write (*body2Write);
513 Assert (fState_ >= State::eHeadersSent);
514 StateTransition_ (State::eCompleted);
515 fUseOutStream_.Flush ();
518 DbgTrace (
"Exception during Response::End () automaticaly triggers Response::Abort()"_f);
521 Ensure (this->responseCompleted ());
525 Ensure (fState_ == State::eCompleted);
526 return not fAborted_;
529void Response::Abort ()
531#if USE_NOISY_TRACE_IN_THIS_MODULE_
535 if (fState_ != State::eCompleted) {
536 fState_ = State::eCompleted;
538 fUseOutStream_.Abort ();
540 if (fBodyRawStream_ !=
nullptr) {
541 fBodyRawStream_.Close ();
544 Ensure (fState_ == State::eCompleted);
547void Response::Redirect (
const URI& url)
550 Require (this->headersCanBeSet ());
551 if (fBodyRawStream_ !=
nullptr) {
552 fBodyRawStream_.Close ();
556 auto& updatableHeaders = this->rwHeaders ();
557 updatableHeaders.connection = IO::Network::HTTP::Headers::eClose;
558 updatableHeaders.location = url;
559 this->status = HTTP::StatusCodes::kMovedPermanently;
560 if (fState_ == State::ePreparingHeaders) {
561 StateTransition_ (State::eHeadersSent);
563 Assert (fState_ >= State::eHeadersSent);
564 StateTransition_ (State::eCompleted);
567void Response::write (
const span<const byte>& bytes)
569#if USE_NOISY_TRACE_IN_THIS_MODULE_
573 Require (not this->responseCompleted ());
574 Require (not this->responseStatusSent () or chunkedTransferMode ());
575 if (fETagDigester_) {
576 fETagDigester_->Write (bytes);
578 fBodyRawStream_.Write (bytes);
579 fBodyRawStreamLength_ += bytes.size ();
580 Assert (fBodyRawStreamLength_ == fBodyRawStream_.GetWriteOffset ());
582 size_t thisChunkSize = fBodyRawStreamLength_ - fBodyRowStreamLengthWhenLastChunkGenerated_;
583 if (thisChunkSize > fAutoTransferChunkSize_.value_or (kAutomaticTransferChunkSize_Default) and not chunkedTransferMode ()) {
587 if (fState_ == State::ePreparingHeaders and chunkedTransferMode ()) {
592 StateTransition_ (State::eHeadersSent);
593 Assert (fState_ >= State::eHeadersSent);
596 FlushNextChunkIfNeeded_ ();
600void Response::write (
const String& s)
603 span<const Character> thisData = s.
GetData (&maybeIgnoreBuf1);
604 string cpStr = codeCvt ().String2Bytes<
string> (thisData);
605 if (not cpStr.empty ()) {
606 write (as_bytes (span{cpStr.c_str (), cpStr.length ()}));
610void Response::printf (
const wchar_t* format, ...)
615 va_start (argsList, format);
616 String tmp = Characters::FormatV (format, argsList);
621void Response::FlushNextChunkIfNeeded_ ()
623 if (not fHeadMode_ and chunkedTransferMode ()) {
624 size_t thisChunkSize = fBodyRawStreamLength_ - fBodyRowStreamLengthWhenLastChunkGenerated_;
625 if (thisChunkSize > fAutoTransferChunkSize_.value_or (kAutomaticTransferChunkSize_Default)) {
627 if (this->fBodyCompressedStream_ !=
nullptr) {
628 if (
auto o = fBodyCompressedStream_.ReadAllAvailable ()) {
633 optional<Memory::InlineBuffer<byte>> aa = fBodyRawStream_.ReadAllAvailable ();
634 if (aa.has_value ()) {
635 data2Write =
BLOB{*aa};
639 if (not data2Write.
empty ()) {
640 WriteChunk_ (data2Write);
641 fBodyRowStreamLengthWhenLastChunkGenerated_ = fBodyRawStreamLength_;
647String Response::ToString ()
const
651 sb <<
"Socket: "sv << fSocket_;
652 sb <<
", chunkedTransferMode: "sv << this->chunkedTransferMode ();
653 sb <<
", hasEntityBody: "sv << this->hasEntityBody ();
654 sb <<
", State: "sv << fState_;
655 sb <<
", CodePage: "sv << fCodePage_;
659 sb <<
", HeadMode: "sv << fHeadMode_;
660 sb <<
", ETagDigester: "sv << fETagDigester_.has_value ();
#define RequireNotReached()
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
#define WeakAssert(c)
A WeakAssert() is for things that aren't guaranteed to be true, but are overwhelmingly likely to be t...
#define AssertNotReached()
CodeCvt unifies byte <-> unicode conversions, vaguely inspired by (and wraps) std::codecvt,...
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual T AsUTF8() const
static span< const CHAR_TYPE > GetData(const PeekSpanData &pds, Memory::StackBuffer< CHAR_TYPE, STACK_BUFFER_SZ > *possiblyUsedBuffer)
return the constant character data inside the string (rep) in the form of a span, possibly quickly an...
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...
ClientErrorException is to capture exceptions caused by a bad (e.g ill-formed) request.
a smart pointer wrapper (like shared_ptr <_IRep>).
nonvirtual bool empty() const
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
OutputStream<>::Ptr is Smart pointer to a stream-based sink of data.
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
void Abort(const Traversal::Iterable< Ptr > &threads)
foreach Thread t: t.Abort ()
Content coding values indicate an encoding transformation that has been or can be applied to an entit...
static const ContentEncoding kDeflate
static const ContentEncoding kGZip
Transfer-Encoding is a hop-by-hop header, that is applied to a message between two nodes,...
static const TransferEncoding kChunked
Options to configure a new SharedMemoryStream; defaults should always work fine, but options can allo...
Execution::InternallySynchronized fInternallySynchronized
controls if the shared stream is automatically synchronized internally so that it can be used by two ...