Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Frameworks/WebServer/Request.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Frameworks/StroikaPreComp.h"
5
6#include <algorithm>
7#include <cstdlib>
8
11#include "Stroika/Foundation/Containers/Common.h"
16#include "Stroika/Foundation/Execution/Throw.h"
17#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
18#include "Stroika/Foundation/IO/Network/HTTP/Versions.h"
20#include "Stroika/Foundation/Streams/MemoryStream.h"
21
22#include "Request.h"
23
24using std::byte;
25
26using namespace Stroika::Foundation;
29using namespace Stroika::Foundation::Memory;
30using namespace Stroika::Foundation::Streams;
31
32using namespace Stroika::Frameworks;
33using namespace Stroika::Frameworks::WebServer;
34
36
37// Comment this in to turn on aggressive noisy DbgTrace in this module
38//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
39
40/*
41 ********************************************************************************
42 *************************** WebServer::Request *********************************
43 ********************************************************************************
44 */
45static_assert (not copyable<Request>); // enforce Satisfies Concepts
46static_assert (movable<Request>);
47
48Request::Request (const Streams::InputStream::Ptr<byte>& inStream)
49 : keepAliveRequested{[qStroika_Foundation_Common_Property_ExtraCaptureStuff] ([[maybe_unused]] const auto* property) {
50 const Request* thisObj = qStroika_Foundation_Common_Property_OuterObjPtr (property, &Request::keepAliveRequested);
51 AssertExternallySynchronizedMutex::ReadContext declareContext{thisObj->_fThisAssertExternallySynchronized};
52 using ConnectionValue = IO::Network::HTTP::Headers::ConnectionValue;
53 if (thisObj->httpVersion == IO::Network::HTTP::Versions::kOnePointZero) {
54 return thisObj->headers ().connection ().value_or (ConnectionValue::eClose) == ConnectionValue::eKeepAlive;
55 }
56 if (thisObj->httpVersion == IO::Network::HTTP::Versions::kOnePointOne) {
57 return thisObj->headers ().connection ().value_or (ConnectionValue::eKeepAlive) == ConnectionValue::eKeepAlive;
58 }
59 return true; // for HTTP 2.0 and later, keep alive is always assumed (double check/reference?)
60 }}
61 , fInputStream_{inStream}
62{
63}
64
66{
67#if USE_NOISY_TRACE_IN_THIS_MODULE_
68 Debug::TraceContextBumper ctx{"Request::GetBody"};
69#endif
70 AssertExternallySynchronizedMutex::WriteContext declareContext{_fThisAssertExternallySynchronized};
71 if (not fBody_.has_value ()) {
72 fBody_ = GetBodyStream ().ReadAll ();
73 }
74 return *fBody_;
75}
76
78{
79 using namespace DataExchange;
80 if (auto oct = contentType ()) {
81 // @todo check 'feature enabled' flag for xml and other types of readers that produce variantvalue - but that reader NYI as of 2024-11-04
82 if (InternetMediaTypeRegistry::sThe->IsA (InternetMediaTypes::kJSON, *oct)) {
83 return Variant::JSON::Reader{}.Read (GetBody ());
84 }
85 static const auto kExcept_ = Execution::RuntimeErrorException{"Unrecognized content type"sv};
86 Execution::Throw (kExcept_);
87 }
88 return VariantValue{};
89}
90
92{
93#if USE_NOISY_TRACE_IN_THIS_MODULE_
94 Debug::TraceContextBumper ctx{"Request::GetBodyStream"};
95#endif
96 AssertExternallySynchronizedMutex::WriteContext declareContext{_fThisAssertExternallySynchronized};
97 if (fBodyInputStream_ == nullptr) {
98 /*
99 * According to https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html:
100 * The presence of a message-body in a request is signaled by the inclusion of
101 * a Content-Length or Transfer-Encoding header field in the request's message-headers
102 */
103 // if we have a content-length, read that many bytes.
104 if (optional<uint64_t> cl = headers ().contentLength ()) {
105 fBodyInputStream_ = InputSubStream::New<byte> (fInputStream_, {}, fInputStream_.GetOffset () + static_cast<size_t> (*cl));
106 }
107 else {
108 /*
109 * @todo FIX - WRONG!!!! - MUST SUPPORT TRANSFER ENCODING IN THIS CASE OR NOTHING
110 *
111 * https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html
112 * The rules for when a message-body is allowed in a message differ for requests and responses.
113 *
114 * The presence of a message-body in a request is signaled by the inclusion of a Content-Length
115 * or Transfer-Encoding header field in the request's message-headers/
116 *
117 * For now - EMPTY is a better failure mode than reading everything and hanging...
118 */
119 fBodyInputStream_ = MemoryStream::New<byte> ();
120 }
121 // @todo See http://stroika-bugs.sophists.com/browse/STK-758 - zip compression support
122 }
123 return fBodyInputStream_;
124}
125
127{
128 AssertExternallySynchronizedMutex::ReadContext declareContext{_fThisAssertExternallySynchronized};
129 StringBuilder sb = inherited::ToString ().SubString (0, -1); // strip trialing '{'
130 // @todo add stuff about body
131 sb << "}"sv;
132 return sb;
133}
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,...
Definition String.h:201
nonvirtual String SubString(SZ from) const
Simple variant-value (case variant union) object, with (variant) basic types analogous to a value in ...
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...
Common::ReadOnlyProperty< optional< InternetMediaType > > contentType
InputStream<>::Ptr is Smart pointer (with abstract Rep) class defining the interface to reading from ...
nonvirtual String ReadAll(size_t upTo=numeric_limits< size_t >::max()) const
nonvirtual SeekOffsetType GetOffset() const
this represents a HTTP request object for the WebServer module
nonvirtual Streams::InputStream::Ptr< byte > GetBodyStream()
Common::ReadOnlyProperty< bool > keepAliveRequested
mostly looks at Connection: ARG header, but if not there takes into account HTTP-version specific def...
nonvirtual DataExchange::VariantValue GetBodyVariantValue()
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43