MLIB
Loading...
Searching...
No Matches
jbridge.h
Go to the documentation of this file.
1/*
2 Copyright (c) Mircea Neacsu (2014-2025) Licensed under MIT License.
3 This is part of MLIB project. See LICENSE file for full license terms.
4*/
5
7#pragma once
8
9#include "httpd.h"
10#include "json.h"
11
12#include <list>
13#include <typeindex>
14
15namespace mlib::http {
16
17// Errors
18#define HTTP_JSON_NOTFOUND -10
19#define HTTP_JSON_DICSTRUC -11
20
21class JSONBridge;
22
24typedef std::function<int (JSONBridge& bridge, void* var)> var_handler;
25
28{
29public:
49
51 class entry;
52 typedef std::list<entry> dictionary;
53 typedef dictionary::iterator dict_ptr;
54 typedef dictionary::const_iterator dict_cptr;
55
56 class entry
57 {
58 public:
59 entry (const std::string& n, void* a, jb_type t, size_t s, size_t c)
60 : name (n)
61 , addr (a)
62 , type (t)
63 , cnt (c)
64 , sz (s)
65 {}
66
67 template <typename T, size_t C>
68 void add_var (T (&var)[C], const std::string& name)
69 {
70 using U = typename std::remove_extent<T>::type;
71 constexpr size_t sz = sizeof (U) * (std::extent_v<T> ? std::extent_v<T> : 1);
72 constexpr jb_type t = std::is_same_v<U, short> ? JT_SHORT
73 : std::is_same_v<U, unsigned short> ? JT_USHORT
74 : std::is_same_v<U, int> ? JT_INT
75 : std::is_same_v<U, unsigned int> ? JT_UINT
76 : std::is_same_v<U, long> ? JT_LONG
77 : std::is_same_v<U, unsigned long> ? JT_ULONG
78 : std::is_same_v<U, float> ? JT_FLT
79 : std::is_same_v<U, double> ? JT_DBL
80 : std::is_same_v<U, bool> ? JT_BOOL
81 : std::is_same_v<U, char> ? JT_CSTR
82 : std::is_same_v<U, std::string> ? JT_STR
83 : std::is_same_v<U, char*> ? JT_PSTR
84 : std::is_same_v<U, const char*> ? JT_PSTR
85 : JT_UNKNOWN;
86 static_assert (t != JT_UNKNOWN, "Invalid array type");
87 if (t == JT_CSTR && sz == 1)
88 children.emplace_back (name, var, t, C, 1); // char var[C]
89 else
90 children.emplace_back (name, var, t, sz, C);
91 }
92
93 template <typename T>
94 std::enable_if_t<std::is_same_v<T, std::string> || std::is_same_v<T, short>
95 || std::is_same_v<T, unsigned short> || std::is_same_v<T, int>
96 || std::is_same_v<T, unsigned int> || std::is_same_v<T, long>
97 || std::is_same_v<T, unsigned long> || std::is_same_v<T, float>
98 || std::is_same_v<T, double> || std::is_same_v<T, bool>>
99 add_var (T& var, const std::string& name)
100 {
101 constexpr jb_type t = std::is_same_v<T, short> ? JT_SHORT
102 : std::is_same_v<T, unsigned short> ? JT_USHORT
103 : std::is_same_v<T, int> ? JT_INT
104 : std::is_same_v<T, unsigned int> ? JT_UINT
105 : std::is_same_v<T, long> ? JT_LONG
106 : std::is_same_v<T, unsigned long> ? JT_ULONG
107 : std::is_same_v<T, float> ? JT_FLT
108 : std::is_same_v<T, double> ? JT_DBL
109 : std::is_same_v<T, bool> ? JT_BOOL
110 : std::is_same_v<T, char> ? JT_CSTR
111 : std::is_same_v<T, std::string> ? JT_STR
112 : std::is_same_v<T, char*> ? JT_PSTR
113 : std::is_same_v<T, const char*> ? JT_PSTR
114 : JT_UNKNOWN;
115 static_assert (t != JT_UNKNOWN, "Invalid variable type");
116 children.emplace_back (name, &var, t, sizeof (T), 1);
117 }
118
119 entry& add_object (const std::string& name)
120 {
121 children.emplace_back (name, nullptr, JT_OBJECT, 0, 1);
122 return *(--children.end ());
123 }
124
125 private:
126 std::string name;
127 void* addr;
128 jb_type type;
129 size_t sz;
130 size_t cnt;
131 dictionary children;
132 friend class JSONBridge;
133 };
134
135 JSONBridge (const char* path);
136 ~JSONBridge ();
137
138 void attach_to (server& server);
139 void lock ();
140 void unlock ();
141 const std::string& path () const;
142 void redirect_to (const std::string& uri);
143 void set_post_action (uri_handler pfn);
144 connection& client ();
145
146 bool parse_urlencoded () const;
147 bool parse_jsonencoded () const;
148
150 template <typename T, size_t C>
151 void add_var (T (&var)[C], const std::string& name)
152 {
153 using U = typename std::remove_extent<T>::type;
154 constexpr size_t sz = sizeof (U) * (std::extent_v<T> ? std::extent_v<T> : 1);
155 constexpr jb_type t = std::is_same_v<U, short> ? JT_SHORT
156 : std::is_same_v<U, unsigned short> ? JT_USHORT
157 : std::is_same_v<U, int> ? JT_INT
158 : std::is_same_v<U, unsigned int> ? JT_UINT
159 : std::is_same_v<U, long> ? JT_LONG
160 : std::is_same_v<U, unsigned long> ? JT_ULONG
161 : std::is_same_v<U, float> ? JT_FLT
162 : std::is_same_v<U, double> ? JT_DBL
163 : std::is_same_v<U, bool> ? JT_BOOL
164 : std::is_same_v<U, char> ? JT_CSTR
165 : std::is_same_v<U, char*> ? JT_PSTR
166 : std::is_same_v<U, const char*> ? JT_PSTR
167 : JT_UNKNOWN;
168 static_assert (t != JT_UNKNOWN, "Invalid array type");
169 if (t == JT_CSTR && sz == 1)
170 dict_.emplace_back (name, var, t, C, 1); // char var[C]
171 else
172 dict_.emplace_back (name, var, t, sz, C);
173 }
174
176 template <typename T>
177 std::enable_if_t<std::is_same_v<T, std::string> || std::is_same_v<T, short>
178 || std::is_same_v<T, unsigned short> || std::is_same_v<T, int>
179 || std::is_same_v<T, unsigned int> || std::is_same_v<T, long>
180 || std::is_same_v<T, unsigned long> || std::is_same_v<T, float>
181 || std::is_same_v<T, double> || std::is_same_v<T, bool>>
182 add_var (T& var, const std::string& name)
183 {
184 constexpr jb_type t = std::is_same_v<T, short> ? JT_SHORT
185 : std::is_same_v<T, unsigned short> ? JT_USHORT
186 : std::is_same_v<T, int> ? JT_INT
187 : std::is_same_v<T, unsigned int> ? JT_UINT
188 : std::is_same_v<T, long> ? JT_LONG
189 : std::is_same_v<T, unsigned long> ? JT_ULONG
190 : std::is_same_v<T, float> ? JT_FLT
191 : std::is_same_v<T, double> ? JT_DBL
192 : std::is_same_v<T, bool> ? JT_BOOL
193 : std::is_same_v<T, char> ? JT_CSTR
194 : std::is_same_v<T, std::string> ? JT_STR
195 : std::is_same_v<T, char*> ? JT_PSTR
196 : std::is_same_v<T, const char*> ? JT_PSTR
197 : JT_UNKNOWN;
198 static_assert (t != JT_UNKNOWN, "Invalid variable type");
199 dict_.emplace_back (name, &var, t, sizeof (T), 1);
200 }
201
202 entry& add_object (const std::string& name);
203 void add_postfun (const std::string& name, uri_handler pfn);
204
205protected:
206
207 erc jsonify (json::node& n, dict_cptr entry);
208 void not_found (const char* varname);
209 bool find (const std::string& name, dict_cptr& found, size_t* idx = 0) const;
210 bool deep_find (const std::string& name, dict_cptr& found, size_t* idx = 0) const;
211
212private:
213 void process_request ();
214 erc json_begin (json::node& obj);
215 erc json_end (json::node& obj);
216 erc serialize_node (json::node& n, dict_cptr v, size_t index = 0);
217 erc deserialize_node (const json::node& n, dict_cptr v, size_t index = 0) const;
218 std::string path_;
219 dictionary dict_;
220 connection* client_;
221 criticalsection in_use;
222 uri_handler post_action;
223 std::string redirect_uri;
224 std::map<std::string, uri_handler> post_handlers;
225
226 static int callback (connection& client, void* ctx);
227 static bool deep_search (const std::string& var, const dictionary& dict, dict_cptr& found);
228};
229
230/*==================== INLINE FUNCTIONS ===========================*/
231
233inline void JSONBridge::lock ()
234{
235 in_use.enter ();
236}
237
239inline void JSONBridge::unlock ()
240{
241 in_use.leave ();
242}
243
245inline const std::string& JSONBridge::path () const
246{
247 return path_;
248}
249
251inline void JSONBridge::redirect_to (const std::string& uri)
252{
253 redirect_uri = uri;
254}
255
258{
259 if (client_)
260 return *client_;
261 else
262 throw std::logic_error ("Missing client connection");
263};
264
272{
273 post_action = pfn;
274}
275
276inline JSONBridge::entry& JSONBridge::add_object (const std::string& name)
277{
278 dict_.emplace_back (name, nullptr, JT_OBJECT, 0, 1);
279 return *(--dict_.end ());
280}
281
291inline void JSONBridge::add_postfun (const std::string& qparam, uri_handler pfn)
292{
293 post_handlers[qparam] = pfn;
294}
295
296} // end namespace mlib::http
Representation of a JSON node.
Definition json.h:59
Lightweight inter-thread synchronization.
Definition critsect.h:25
objects returned as a function result or thrown directly.
Definition errorcode.h:68
Definition jbridge.h:57
JSON objects support.
Definition jbridge.h:28
connection & client()
Return currently connected client (if any)
Definition jbridge.h:257
JSONBridge(const char *path)
Creates a JSONBridge object for the given path.
Definition jbridge.cpp:52
void add_postfun(const std::string &name, uri_handler pfn)
Add a handler function invoked in response to a POST request with an additional parameter.
Definition jbridge.h:291
void attach_to(server &server)
Attach JSONBridge object to a HTTP server.
Definition jbridge.cpp:64
void set_post_action(uri_handler pfn)
Set the function invoked after successful processing of a POST request.
Definition jbridge.h:271
void add_var(T(&var)[C], const std::string &name)
add array
Definition jbridge.h:151
erc jsonify(json::node &n, dict_cptr entry)
Serializes a variable to JSON format.
Definition jbridge.cpp:108
bool find(const std::string &name, dict_cptr &found, size_t *idx=0) const
Search a variable in JSON dictionary.
Definition jbridge.cpp:260
const std::string & path() const
Return the root path where bridge is attached.
Definition jbridge.h:245
std::enable_if_t< std::is_same_v< T, std::string >||std::is_same_v< T, short >||std::is_same_v< T, unsigned short >||std::is_same_v< T, int >||std::is_same_v< T, unsigned int >||std::is_same_v< T, long >||std::is_same_v< T, unsigned long >||std::is_same_v< T, float >||std::is_same_v< T, double >||std::is_same_v< T, bool > > add_var(T &var, const std::string &name)
add variable of one of basic types
Definition jbridge.h:182
void redirect_to(const std::string &uri)
Set default redirection target for POST requests.
Definition jbridge.h:251
void unlock()
Leave the critical section associated with this bridge.
Definition jbridge.h:239
jb_type
Dictionary entry types.
Definition jbridge.h:32
@ JT_DBL
double
Definition jbridge.h:41
@ JT_USHORT
unsigned short int
Definition jbridge.h:35
@ JT_INT
int
Definition jbridge.h:36
@ JT_SHORT
short int
Definition jbridge.h:34
@ JT_UINT
unsigned int
Definition jbridge.h:37
@ JT_OBJECT
composite object
Definition jbridge.h:46
@ JT_CSTR
char[]
Definition jbridge.h:43
@ JT_LONG
long
Definition jbridge.h:38
@ JT_FLT
float
Definition jbridge.h:40
@ JT_BOOL
bool
Definition jbridge.h:45
@ JT_ULONG
unsigned long
Definition jbridge.h:39
@ JT_POSTFUN
POST function call.
Definition jbridge.h:47
@ JT_PSTR
char*
Definition jbridge.h:42
@ JT_STR
std::string
Definition jbridge.h:44
bool parse_urlencoded() const
Parse the URL-encoded body of a POST request assigning new values to all variables.
Definition jbridge.cpp:332
void lock()
Enter the critical section associated with this bridge.
Definition jbridge.h:233
Representation of a HTTP client connection request.
Small multi-threaded HTTP server.
Definition httpd.h:154
Implementation of http::server and http::connection classes.
std::function< int(connection &client, void *info)> uri_handler
User defined URL handler function.
Definition httpd.h:46
std::function< int(JSONBridge &bridge, void *var)> var_handler
User defined variable handler function.
Definition jbridge.h:24
Definition of json::node class.