Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Basic.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Frameworks/StroikaPreComp.h"
5
9#include "Stroika/Foundation/Containers/Mapping.h"
13#include "Stroika/Foundation/IO/Network/HTTP/ClientErrorException.h"
14
15#include "Basic.h"
16
17using namespace Stroika::Foundation;
21
22using namespace Stroika::Frameworks;
23using namespace Stroika::Frameworks::WebService;
24
26
27// Comment this in to turn on aggressive noisy DbgTrace in this module
28//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1
29
30/*
31 ********************************************************************************
32 ************************ WebService::Server::ExpectedMethod ********************
33 ********************************************************************************
34 */
35void WebService::Server::ExpectedMethod (const Request& request, const Set<String>& methods, const optional<String>& fromInMessage)
36{
37#if USE_NOISY_TRACE_IN_THIS_MODULE_
39 "WebService::Server::ExpectedMethod", "request={}, methods={}, fromInMessage={}"_f, request, methods, fromInMessage)};
40#endif
41 if (not methods.Contains (request.httpMethod ())) {
42 Execution::Throw (ClientErrorException{"Received HTTP method '{}'{}, but expected one from {}"_f(
43 request.httpMethod (), (fromInMessage ? (L" from '"sv + *fromInMessage + L"'"sv).As<wstring> ().c_str () : L""), methods)});
44 }
45}
46
47void WebService::Server::ExpectedMethod (const Request& request, const Iterable<String>& methods, const optional<String>& fromInMessage)
48{
49 ExpectedMethod (request, Set<String>{methods}, fromInMessage);
50}
51
52void WebService::Server::ExpectedMethod (const Request& request, const WebServiceMethodDescription& wsMethodDescription)
53{
54 if (wsMethodDescription.fAllowedMethods) {
55 ExpectedMethod (request, *wsMethodDescription.fAllowedMethods, wsMethodDescription.fOperation);
56 }
57}
58
59/*
60 ********************************************************************************
61 ************************ WebService::Server::WriteDocsPage *********************
62 ********************************************************************************
63 */
64const String WebService::Server::DocsOptions::kDefaultCSSSection =
65 "div.mainDocs {margin-left: .3in; margin-right: .3in; }\n"
66 "div.mainDocs div { padding-top: 6pt; padding-bottom: 6pt; }\n"
67 "div.OpenAPI { padding-top: 12pt; padding-bottom: 12pt; }\n"
68 "div.curlExample {margin-left: .3in; margin-top: .1in; margin-bottom:.1in; font-family: \"Courier New\", Courier, \"Lucida Sans "
69 "Typewriter\", \"Lucida Typewriter\", monospace; font-size: 9pt; font-weight: bold;}\n"
70 "div.curlExample div { padding-top: 2pt; padding-bottom: 2pt; }\n"
71 "div.introduction div { padding-top: 2pt; padding-bottom: 2pt; }\n"sv;
72
73void WebService::Server::WriteDocsPage (Response& response, const Sequence<WebServiceMethodDescription>& operations, const DocsOptions& docsOptions)
74{
75 response.contentType = DataExchange::InternetMediaTypes::kHTML;
76 response.writeln ("<html>"sv);
77 response.writeln ("<style type=\"text/css\">"sv);
78 response.writeln (docsOptions.fCSSSection);
79 response.writeln ("</style>"sv);
80 response.writeln ("<body>"sv);
81 response.write ("<h1>{}</h1>"_f, docsOptions.fH1Text);
82 response.write ("<div class='introduction'>{}</div>\n"_f, docsOptions.fIntroductoryText);
83
84 if (docsOptions.fOpenAPISpecificationURI) {
85 response.write ("<div class='OpenAPI'>Download <a href={}>OpenAPI File</a></div>\n"_f, *docsOptions.fOpenAPISpecificationURI);
86 }
87 response.writeln ("<ul>"sv);
88 auto substVars = [&] (const String& origStr) {
89 String str = origStr;
90 for (const auto& i : docsOptions.fVariables2Substitute) {
91 str = str.ReplaceAll ("{{" + i.fKey + "}}", i.fValue);
92 }
93 return str;
94 };
95 auto writeDocs = [&] (const String& methodName, const String& docs, const String& exampleCall) {
96 response.writeln ("<li>"sv);
97 response.write ("<a href=\"/{}\">{}</a>"_f, methodName, methodName);
98 response.write ("<div class='mainDocs'>{}</div>"_f, docs);
99 response.write ("<div class='curlExample'>{}</div>"_f, exampleCall);
100 response.writeln ("</li>"sv);
101 };
102 for (const WebServiceMethodDescription& i : operations) {
103 StringBuilder tmpDocs;
104 if (i.fDetailedDocs) {
105 i.fDetailedDocs->Apply ([&] (const String& i) { tmpDocs << "<div>"sv << substVars (i) << "</div>"sv; });
106 }
107 StringBuilder tmpCurl;
108 if (i.fCurlExample) {
109 i.fCurlExample->Apply ([&] (const String& i) { tmpCurl << "<div>"sv << substVars (i) << "</div>"sv; });
110 }
111 writeDocs (i.fOperation, tmpDocs, tmpCurl);
112 }
113 response.writeln ("</ul>"sv);
114 response.writeln ("</body>"sv);
115 response.writeln ("</html>"sv);
116}
#define Stroika_Foundation_Debug_OptionalizeTraceArgs(...)
Definition Trace.h:270
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 ReplaceAll(const RegularExpression &regEx, const String &with) const
Definition String.cpp:1155
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Definition Sequence.h:187
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
Definition Set.h:105
ClientErrorException is to capture exceptions caused by a bad (e.g ill-formed) request.
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43