4#include "Stroika/Frameworks/StroikaPreComp.h"
6#include "Stroika/Foundation/Characters/FloatConversion.h"
7#include "Stroika/Foundation/Characters/String2Int.h"
9#include "Stroika/Foundation/Common/Property.h"
11#include "Stroika/Foundation/IO/Network/HTTP/Exception.h"
12#include "Stroika/Foundation/IO/Network/HTTP/Headers.h"
13#include "Stroika/Foundation/IO/Network/HTTP/Methods.h"
16#include "Stroika/Frameworks/WebServer/ConnectionManager.h"
17#include "Stroika/Frameworks/WebServer/Router.h"
18#include "Stroika/Frameworks/WebService/Server/Basic.h"
19#include "Stroika/Frameworks/WebService/Server/ObjectRequestHandler.h"
20#include "Stroika/Frameworks/WebService/Server/VariantValue.h"
24#include "AppVersion.h"
33using namespace Stroika::Foundation::Traversal;
36using namespace Stroika::Frameworks::WebService;
37using namespace Stroika::Frameworks::WebService::Server;
38using namespace Stroika::Frameworks::WebService::Server::VariantValue;
41using Memory::MakeSharedPtr;
43using Stroika::Frameworks::WebServer::Response;
46using namespace StroikaSample::WebServices;
49 const Headers kDefaultResponseHeaders_{[] () {
51 h.
server =
"Stroika-Sample-WebServices/"_k + AppVersion::kVersion.AsMajorMinorString ();
69class WebServer::Rep_ {
72 shared_ptr<IWSAPI> fWSImpl_;
75 static const WebServiceMethodDescription kVariables_;
77 static const WebServiceMethodDescription kPlus_;
78 static const WebServiceMethodDescription kMinus;
79 static const WebServiceMethodDescription kTimes;
80 static const WebServiceMethodDescription kDivide;
82 Rep_ (uint16_t portNumber,
const shared_ptr<IWSAPI>& wsImpl)
84 Route{
""_RegEx, DefaultPage_},
86 Route{HTTP::MethodsRegEx::kPost,
"SetAppState"_RegEx, SetAppState_},
89 [] (
Request&, Response& response) {
90 response.write (
"FRED");
91 response.contentType = InternetMediaTypes::kText_PLAIN;
98 Route{
"variables(/?)"_RegEx,
99 [
this] (
Message& m) { WriteResponse (m.rwResponse (), kVariables_, kMapper.
FromObject (fWSImpl_->Variables_GET ())); }},
100 Route{
"variables/(.+)"_RegEx,
102 WriteResponse (m.rwResponse (), kVariables_, kMapper.
FromObject (fWSImpl_->Variables_GET (varName)));
104 Route{HTTP::MethodsRegEx::kPostOrPut,
"variables/(.+)"_RegEx,
106 optional<Number> number;
110 if (m.request ().contentType () and
118 static const String kValueParamName_ =
"value"sv;
120 number = Model::kMapper.ToObject<Number> (args.
LookupValue (kValueParamName_));
124 static const String kValueParamName_ =
"value"sv;
130 number = Model::kMapper.ToObject<Number> (args.
LookupValue (kValueParamName_));
135 fWSImpl_->Variables_SET (varName, *number);
136 WriteResponse (m.rwResponse (), kVariables_);
138 Route{HTTP::MethodsRegEx::kDelete,
"variables/(.+)"_RegEx,
143 fWSImpl_->Variables_DELETE (varName);
144 WriteResponse (m.rwResponse (), kVariables_);
150 Route{HTTP::MethodsRegEx::kPost,
"plus"_RegEx,
152 [
this] (Number arg1, Number arg2) {
return fWSImpl_->plus (arg1, arg2); }}},
153 Route{HTTP::MethodsRegEx::kPost,
"minus"_RegEx,
155 [
this] (Number arg1, Number arg2) {
return fWSImpl_->minus (arg1, arg2); }}},
156 Route{HTTP::MethodsRegEx::kPost,
"times"_RegEx,
158 [
this] (Number arg1, Number arg2) {
return fWSImpl_->times (arg1, arg2); }}},
159 Route{HTTP::MethodsRegEx::kPost,
"divide"_RegEx,
161 [
this] (Number arg1, Number arg2) {
return fWSImpl_->divide (arg1, arg2); }}},
162 Route{HTTP::MethodsRegEx::kPost,
"test-void-return"_RegEx,
176 static void DefaultPage_ (
Request&, Response& response)
178 WriteDocsPage (response,
186 DocsOptions{
"Stroika Sample WebService - Web Methods"_k,
"Note - curl lines all in bash quoting syntax"_k});
188 static void SetAppState_ (
Message& message)
191 message.
rwResponse ().writeln (
"<html><body><p>Hi SetAppState ("sv + argsAsString +
")</p></body></html>"sv);
192 message.
rwResponse ().contentType = InternetMediaTypes::kHTML;
199const WebServiceMethodDescription WebServer::Rep_::kVariables_{
201 Set<String>{HTTP::Methods::kGet, HTTP::Methods::kPost, HTTP::Methods::kDelete},
202 InternetMediaTypes::kJSON,
204 Sequence<String>{
"curl http://localhost:8080/variables -v --output -",
"curl http://localhost:8080/variables/x -v --output -",
205 "curl -X POST http://localhost:8080/variables/x -v --output -",
206 "curl -H \"Content-Type: application/json\" -X POST -d '{\"value\": 3}' http://localhost:8080/variables/x --output -",
207 "curl -H \"Content-Type: text/plain\" -X POST -d 3 http://localhost:8080/variables/x --output -"},
208 Sequence<String>{
"@todo - this is a rough draft (but functional). It could use alot of cleanup and review to see WHICH way I recommend "
209 "using, and just provide the recommended ways in samples"},
212const WebServiceMethodDescription WebServer::Rep_::kPlus_{
215 InternetMediaTypes::kJSON,
218 "curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\": 3, \"arg2\": 5 }' http://localhost:8080/plus --output -",
219 "curl -X POST 'http://localhost:8080/plus?arg1=3&arg2=5' --output -",
223const WebServiceMethodDescription WebServer::Rep_::kMinus{
226 InternetMediaTypes::kJSON,
229 "curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\": 4.5, \"arg2\": -3.23 }' http://localhost:8080/minus --output -",
233const WebServiceMethodDescription WebServer::Rep_::kTimes{
236 InternetMediaTypes::kJSON,
239 "curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + 4i\", \"arg2\": 3.2 }' http://localhost:8080/times "
241 "curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + i\", \"arg2\": \"2 - i\" }' http://localhost:8080/times "
246const WebServiceMethodDescription WebServer::Rep_::kDivide{
249 InternetMediaTypes::kJSON,
252 "curl -H \"Content-Type: application/json\" -X POST -d '{\"arg1\":\"2 + i\", \"arg2\": 0 }' http://localhost:8080/divide --output "
258WebServer::WebServer (uint16_t portNumber,
const shared_ptr<IWSAPI>& wsImpl)
auto MakeSharedPtr(ARGS_TYPE &&... args) -> shared_ptr< T >
same as make_shared, but if type T has block allocation, then use block allocation for the 'shared pa...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
A Mapping uniquely associates two elements: a key and a value (use Assocation to allow multiple value...
nonvirtual mapped_type LookupValue(ArgByValueType< key_type > key, ArgByValueType< mapped_type > defaultValue=mapped_type{}) const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual VariantValue FromObject(const T &from) const
nonvirtual T ToObject(const VariantValue &v) const
Simple variant-value (case variant union) object, with (variant) basic types analogous to a value in ...
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
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.
Common::ReadOnlyProperty< Response & > rwResponse
Common::ReadOnlyProperty< Request & > rwRequest
this represents a HTTP request object for the WebServer module
ObjectRequestHandler::Factory is a way to construct a WebServer::RequestHandler from an ObjectVariant...
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Traversal::Iterable< SocketAddress > SocketAddresses(const Traversal::Iterable< InternetAddress > &internetAddresses, PortType portNumber)
Traversal::Iterable< InternetAddress > InternetAddresses_Any(InternetProtocol::IP::IPVersionSupport ipSupport=InternetProtocol::IP::IPVersionSupport::eDEFAULT)
Ptr New(const InputStream::Ptr< byte > &src, optional< AutomaticCodeCvtFlags > codeCvtFlags={}, optional< SeekableFlag > seekable={}, ReadAhead readAhead=eReadAheadAllowed)
Create an InputStream::Ptr<Character> from the arguments (usually binary source) - which can be used ...
ConnectionManager::Options specify things like default headers, caching policies, binding flags (not ...
optional< Headers > fDefaultResponseHeaders
Options for ObjectRequestHandler - mostly the ObjectVariantMapper, but also a few others depending on...