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 "http.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 jbridge;
22
24typedef std::function<int (jbridge& bridge, void* var)> var_handler;
25
27class jbridge
28{
29public:
49
50 class entry;
51
53 typedef std::list<entry> dictionary;
54
56 typedef dictionary::iterator dict_ptr;
57 typedef dictionary::const_iterator dict_cptr;
59
61 class entry
62 {
63 public:
64 entry (const std::string& n, void* a, jb_type t, size_t s, size_t c)
65 : name (n)
66 , addr (a)
67 , type (t)
68 , cnt (c)
69 , sz (s)
70 {}
71
78 template <typename T, size_t C>
79 void add_var (T (&var)[C], const std::string& name)
80 {
81 using U = typename std::remove_extent<T>::type;
82 constexpr size_t sz = sizeof (U) * (std::extent_v<T> ? std::extent_v<T> : 1);
83 constexpr jb_type t = std::is_same_v<U, short> ? JT_SHORT
84 : std::is_same_v<U, unsigned short> ? JT_USHORT
85 : std::is_same_v<U, int> ? JT_INT
86 : std::is_same_v<U, unsigned int> ? JT_UINT
87 : std::is_same_v<U, long> ? JT_LONG
88 : std::is_same_v<U, unsigned long> ? JT_ULONG
89 : std::is_same_v<U, float> ? JT_FLT
90 : std::is_same_v<U, double> ? JT_DBL
91 : std::is_same_v<U, bool> ? JT_BOOL
92 : std::is_same_v<U, char> ? JT_CSTR
93 : std::is_same_v<U, std::string> ? JT_STR
94 : std::is_same_v<U, char*> ? JT_PSTR
95 : std::is_same_v<U, const char*> ? JT_PSTR
96 : JT_UNKNOWN;
97 static_assert (t != JT_UNKNOWN, "Invalid array type");
98 if (t == JT_CSTR && sz == 1)
99 children.emplace_back (name, var, t, C, 1); // char var[C]
100 else
101 children.emplace_back (name, var, t, sz, C);
102 }
103
110 template <typename T>
111 std::enable_if_t<std::is_same_v<T, std::string> || std::is_same_v<T, short>
112 || std::is_same_v<T, unsigned short> || std::is_same_v<T, int>
113 || std::is_same_v<T, unsigned int> || std::is_same_v<T, long>
114 || std::is_same_v<T, unsigned long> || std::is_same_v<T, float>
115 || std::is_same_v<T, double> || std::is_same_v<T, bool>>
116 add_var (T& var, const std::string& name)
117 {
118 constexpr jb_type t = std::is_same_v<T, short> ? JT_SHORT
119 : std::is_same_v<T, unsigned short> ? JT_USHORT
120 : std::is_same_v<T, int> ? JT_INT
121 : std::is_same_v<T, unsigned int> ? JT_UINT
122 : std::is_same_v<T, long> ? JT_LONG
123 : std::is_same_v<T, unsigned long> ? JT_ULONG
124 : std::is_same_v<T, float> ? JT_FLT
125 : std::is_same_v<T, double> ? JT_DBL
126 : std::is_same_v<T, bool> ? JT_BOOL
127 : std::is_same_v<T, char> ? JT_CSTR
128 : std::is_same_v<T, std::string> ? JT_STR
129 : std::is_same_v<T, char*> ? JT_PSTR
130 : std::is_same_v<T, const char*> ? JT_PSTR
131 : JT_UNKNOWN;
132 static_assert (t != JT_UNKNOWN, "Invalid variable type");
133 children.emplace_back (name, &var, t, sizeof (T), 1);
134 }
135
136 entry& add_object (const std::string& name)
137 {
138 children.emplace_back (name, nullptr, JT_OBJECT, 0, 1);
139 return *(--children.end ());
140 }
141
142 private:
143 std::string name;
144 void* addr;
145 jb_type type;
146 size_t sz;
147 size_t cnt;
148 dictionary children;
149 friend class jbridge;
150 };
151
152 jbridge (const char* path);
153 ~jbridge ();
154
155 void attach_to (server& server);
156 void lock ();
157 void unlock ();
158 const std::string& path () const;
159 void redirect_to (const std::string& uri);
160 void set_post_action (uri_handler pfn);
161 connection& client ();
162
163 bool parse_urlencoded () const;
164 bool parse_jsonencoded () const;
165
167 template <typename T, size_t C>
168 void add_var (T (&var)[C], const std::string& name)
169 {
170 using U = typename std::remove_extent<T>::type;
171 constexpr size_t sz = sizeof (U) * (std::extent_v<T> ? std::extent_v<T> : 1);
172 constexpr jb_type t = std::is_same_v<U, short> ? JT_SHORT
173 : std::is_same_v<U, unsigned short> ? JT_USHORT
174 : std::is_same_v<U, int> ? JT_INT
175 : std::is_same_v<U, unsigned int> ? JT_UINT
176 : std::is_same_v<U, long> ? JT_LONG
177 : std::is_same_v<U, unsigned long> ? JT_ULONG
178 : std::is_same_v<U, float> ? JT_FLT
179 : std::is_same_v<U, double> ? JT_DBL
180 : std::is_same_v<U, bool> ? JT_BOOL
181 : std::is_same_v<U, char> ? JT_CSTR
182 : std::is_same_v<U, char*> ? JT_PSTR
183 : std::is_same_v<U, const char*> ? JT_PSTR
184 : JT_UNKNOWN;
185 static_assert (t != JT_UNKNOWN, "Invalid array type");
186 if (t == JT_CSTR && sz == 1)
187 dict_.emplace_back (name, var, t, C, 1); // char var[C]
188 else
189 dict_.emplace_back (name, var, t, sz, C);
190 }
191
193 template <typename T>
194 std::enable_if_t<std::is_same_v<T, std::string> || std::is_same_v<T, short>
195 || std::is_same_v<T, unsigned short> || std::is_same_v<T, int>
196 || std::is_same_v<T, unsigned int> || std::is_same_v<T, long>
197 || std::is_same_v<T, unsigned long> || std::is_same_v<T, float>
198 || std::is_same_v<T, double> || std::is_same_v<T, bool>>
199 add_var (T& var, const std::string& name)
200 {
201 constexpr jb_type t = std::is_same_v<T, short> ? JT_SHORT
202 : std::is_same_v<T, unsigned short> ? JT_USHORT
203 : std::is_same_v<T, int> ? JT_INT
204 : std::is_same_v<T, unsigned int> ? JT_UINT
205 : std::is_same_v<T, long> ? JT_LONG
206 : std::is_same_v<T, unsigned long> ? JT_ULONG
207 : std::is_same_v<T, float> ? JT_FLT
208 : std::is_same_v<T, double> ? JT_DBL
209 : std::is_same_v<T, bool> ? JT_BOOL
210 : std::is_same_v<T, char> ? JT_CSTR
211 : std::is_same_v<T, std::string> ? JT_STR
212 : std::is_same_v<T, char*> ? JT_PSTR
213 : std::is_same_v<T, const char*> ? JT_PSTR
214 : JT_UNKNOWN;
215 static_assert (t != JT_UNKNOWN, "Invalid variable type");
216 dict_.emplace_back (name, &var, t, sizeof (T), 1);
217 }
218
219 entry& add_object (const std::string& name);
220 void add_postfun (const std::string& name, uri_handler pfn);
221
222protected:
223
224 erc jsonify (json::node& n, dict_cptr entry);
225 void not_found (const char* varname);
226 bool find (const std::string& name, dict_cptr& found, size_t* idx = 0) const;
227 bool deep_find (const std::string& name, dict_cptr& found, size_t* idx = 0) const;
228
229private:
230 void process_request ();
231 erc json_begin (json::node& obj);
232 erc json_end (json::node& obj);
233 erc serialize_node (json::node& n, dict_cptr v, size_t index = 0);
234 erc deserialize_node (const json::node& n, dict_cptr v, size_t index = 0) const;
235 std::string path_;
236 dictionary dict_;
237 connection* client_;
238 criticalsection in_use;
239 uri_handler post_action;
240 std::string redirect_uri;
241 std::map<std::string, uri_handler> post_handlers;
242
243 static int callback (connection& client, void* ctx);
244 static bool deep_search (const std::string& var, const dictionary& dict, dict_cptr& found);
245};
246
247/*==================== INLINE FUNCTIONS ===========================*/
248
250inline void jbridge::lock ()
251{
252 in_use.enter ();
253}
254
256inline void jbridge::unlock ()
257{
258 in_use.leave ();
259}
260
262inline const std::string& jbridge::path () const
263{
264 return path_;
265}
266
268inline void jbridge::redirect_to (const std::string& uri)
269{
270 redirect_uri = uri;
271}
272
275{
276 if (client_)
277 return *client_;
278 else
279 throw std::logic_error ("Missing client connection");
280};
281
289{
290 post_action = pfn;
291}
292
298inline jbridge::entry& jbridge::add_object (const std::string& name)
299{
300 dict_.emplace_back (name, nullptr, JT_OBJECT, 0, 1);
301 return *(--dict_.end ());
302}
303
313inline void jbridge::add_postfun (const std::string& qparam, uri_handler pfn)
314{
315 post_handlers[qparam] = pfn;
316}
317
318} // end namespace mlib::http
Lightweight inter-thread synchronization.
Definition critsect.h:27
objects returned as a function result or thrown directly.
Definition errorcode.h:73
Representation of a HTTP client connection request.
JSON data dictionary entry.
Definition jbridge.h:62
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 a variable to data dictionary.
Definition jbridge.h:116
void add_var(T(&var)[C], const std::string &name)
Add an array to data dictionary.
Definition jbridge.h:79
JSON objects support.
void unlock()
Leave the critical section associated with this bridge.
Definition jbridge.h:256
entry & add_object(const std::string &name)
Add an object to data dictionary.
Definition jbridge.h:298
dictionary::const_iterator dict_cptr
Dictionary iterator.
Definition jbridge.h:57
erc jsonify(json::node &n, dict_cptr entry)
Serializes a variable to JSON format.
Definition jbridge.cpp:110
dictionary::iterator dict_ptr
Dictionary iterator.
Definition jbridge.h:56
void set_post_action(uri_handler pfn)
Set the function invoked after successful processing of a POST request.
Definition jbridge.h:288
connection & client()
Return currently connected client (if any)
Definition jbridge.h:274
void redirect_to(const std::string &uri)
Set default redirection target for POST requests.
Definition jbridge.h:268
void not_found(const char *varname)
Generate 410 response if a variable was not found in JSON dictionary.
Definition jbridge.cpp:249
std::list< entry > dictionary
Data dictionary structure.
Definition jbridge.h:53
bool parse_urlencoded() const
Parse the URL-encoded body of a POST request assigning new values to all variables.
Definition jbridge.cpp:338
const std::string & path() const
Return the root path where bridge is attached.
Definition jbridge.h:262
jbridge(const char *path)
Creates a jbridge object for the given path.
Definition jbridge.cpp:54
void lock()
Enter the critical section associated with this bridge.
Definition jbridge.h:250
void attach_to(server &server)
Attach jbridge object to a HTTP server.
Definition jbridge.cpp:66
void add_var(T(&var)[C], const std::string &name)
add array
Definition jbridge.h:168
bool find(const std::string &name, dict_cptr &found, size_t *idx=0) const
Search a variable in JSON dictionary.
Definition jbridge.cpp:263
bool deep_find(const std::string &name, dict_cptr &found, size_t *idx=0) const
Search for a variable name in JSON dictionary.
Definition jbridge.cpp:312
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:199
jb_type
Dictionary entry types.
Definition jbridge.h:32
@ JT_FLT
float
Definition jbridge.h:40
@ JT_ULONG
unsigned long
Definition jbridge.h:39
@ JT_POSTFUN
POST function call.
Definition jbridge.h:47
@ JT_INT
int
Definition jbridge.h:36
@ JT_STR
std::string
Definition jbridge.h:44
@ JT_LONG
long
Definition jbridge.h:38
@ JT_CSTR
char[]
Definition jbridge.h:43
@ JT_OBJECT
composite object
Definition jbridge.h:46
@ JT_SHORT
short int
Definition jbridge.h:34
@ JT_DBL
double
Definition jbridge.h:41
@ JT_UINT
unsigned int
Definition jbridge.h:37
@ JT_PSTR
char*
Definition jbridge.h:42
@ JT_USHORT
unsigned short int
Definition jbridge.h:35
@ JT_BOOL
bool
Definition jbridge.h:45
bool parse_jsonencoded() const
Parse a JSON-encoded body of a POST message.
Definition jbridge.cpp:411
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:313
Representation of a JSON node.
Definition json.h:61
Definition of mlib::http::server and mlib::http::connection classes.
std::function< int(connection &client, void *info)> uri_handler
User defined URL handler function.
Definition http.h:50
std::function< int(jbridge &bridge, void *var)> var_handler
User defined variable handler function.
Definition jbridge.h:24
Definition of mlib::json::node class.