GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/microservices/webserver_service.c
Date: 2026-10-19 17:06:30
Exec Total Coverage
Lines: 82 235 34.9%
Functions: 6 17 35.3%
Branches: 18 86 20.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2026, Stefan Meislinger |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/tech/microservices/webserver_service.h"
30 #include "gate/results.h"
31 #include "gate/net/httpservers.h"
32 #include "gate/times.h"
33
34 #define WEBSERVER_CONFIG_NAME GATE_STRUCT_ROOT_NAME GATE_STRUCT_SEPARATOR WEBSERVER_ROOT_NAME GATE_STRUCT_SEPARATOR "config"
35
36 #define WEBSERVER_CONFIG_VDIR_NAME WEBSERVER_CONFIG_NAME GATE_STRUCT_SEPARATOR "vdir"
37 #define WEBSERVER_CONFIG_HTTPHANDLER_NAME WEBSERVER_CONFIG_NAME GATE_STRUCT_SEPARATOR "httphandler"
38
39
40 static gate_struct_item_t const webservice_request_members[] =
41 {
42 GATE_STRUCT_ITEM(gate_microservice_webservice_request_t, GATE_TYPE_STRING, verb),
43 GATE_STRUCT_ITEM(gate_microservice_webservice_request_t, GATE_TYPE_STRING, path),
44 GATE_STRUCT_ITEM(gate_microservice_webservice_request_t, GATE_TYPE_BLOB, content),
45 GATE_STRUCT_ITEM(gate_microservice_webservice_request_t, GATE_TYPE_STRING, content_type),
46 };
47
48 static gate_struct_descriptor_t const webservice_request_descriptor =
49 {
50 WEBSERVER_WEBSERVICE_REQUEST,
51 webservice_request_members,
52 sizeof(webservice_request_members) / sizeof(webservice_request_members[0]),
53 sizeof(gate_microservice_webservice_request_t)
54 };
55
56 ✗ gate_result_t gate_microservice_webservice_request_ctor(void* target, void const* src)
57 {
58 gate_result_t ret;
59 ✗ gate_microservice_webservice_request_t const* ptr_src = (gate_microservice_webservice_request_t const*)src;
60 ✗ gate_microservice_webservice_request_t* ptr_dst = (gate_microservice_webservice_request_t*)target;
61
62 ✗ if (src == NULL)
63 {
64 ✗ ret = gate_struct_init(&ptr_dst->struct_base, &webservice_request_descriptor);
65 }
66 else
67 {
68 ✗ gate_mem_clear(ptr_dst, sizeof(gate_microservice_webservice_request_t));
69 ✗ ret = gate_struct_copy(&ptr_dst->struct_base, &ptr_src->struct_base);
70 }
71 ✗ return ret;
72 }
73
74
75
76 static gate_struct_item_t const webservice_response_members[] =
77 {
78 GATE_STRUCT_ITEM(gate_microservice_webservice_response_t, GATE_TYPE_UI32, status_code),
79 GATE_STRUCT_ITEM(gate_microservice_webservice_response_t, GATE_TYPE_BLOB, content),
80 GATE_STRUCT_ITEM(gate_microservice_webservice_response_t, GATE_TYPE_STRING, content_type),
81 };
82
83 static gate_struct_descriptor_t const webservice_response_descriptor =
84 {
85 WEBSERVER_WEBSERVICE_RESPONSE,
86 webservice_response_members,
87 sizeof(webservice_response_members) / sizeof(webservice_response_members[0]),
88 sizeof(gate_microservice_webservice_response_t)
89 };
90
91 ✗ gate_result_t gate_microservice_webservice_response_ctor(void* target, void const* src)
92 {
93 gate_result_t ret;
94 ✗ gate_microservice_webservice_response_t const* ptr_src = (gate_microservice_webservice_response_t const*)src;
95 ✗ gate_microservice_webservice_response_t* ptr_dst = (gate_microservice_webservice_response_t*)target;
96
97 ✗ if (src == NULL)
98 {
99 ✗ ret = gate_struct_init(&ptr_dst->struct_base, &webservice_response_descriptor);
100 }
101 else
102 {
103 ✗ gate_mem_clear(ptr_dst, sizeof(gate_microservice_webservice_response_t));
104 ✗ ret = gate_struct_copy(&ptr_dst->struct_base, &ptr_src->struct_base);
105 }
106 ✗ return ret;
107 }
108
109
110
111 typedef struct webserver_config_vdir_class
112 {
113 gate_struct_t struct_base;
114
115 gate_string_t webpath;
116 gate_string_t filepath;
117 gate_bool_t webdav;
118 } webserver_config_vdir_t;
119
120 static gate_struct_item_t const webserver_config_vdir_members[] =
121 {
122 GATE_STRUCT_ITEM(webserver_config_vdir_t, GATE_TYPE_STRING, webpath),
123 GATE_STRUCT_ITEM(webserver_config_vdir_t, GATE_TYPE_STRING, filepath),
124 GATE_STRUCT_ITEM(webserver_config_vdir_t, GATE_TYPE_BOOL, webdav),
125 };
126
127 static gate_struct_descriptor_t const webserver_config_vdir_descriptor =
128 {
129 WEBSERVER_CONFIG_VDIR_NAME,
130 webserver_config_vdir_members,
131 sizeof(webserver_config_vdir_members) / sizeof(webserver_config_vdir_members[0]),
132 sizeof(webserver_config_vdir_t)
133 };
134
135 ✗ static gate_result_t GATE_CALL webserver_config_vdir_ctor(void* target, void const* src)
136 {
137 gate_result_t ret;
138 ✗ webserver_config_vdir_t const* ptr_src = (webserver_config_vdir_t const*)src;
139 ✗ webserver_config_vdir_t* ptr_dst = (webserver_config_vdir_t*)target;
140
141 ✗ if (src == NULL)
142 {
143 ✗ ret = gate_struct_init(&ptr_dst->struct_base, &webserver_config_vdir_descriptor);
144 }
145 else
146 {
147 ✗ gate_mem_clear(ptr_dst, sizeof(webserver_config_vdir_t));
148 ✗ ret = gate_struct_copy(&ptr_dst->struct_base, &ptr_src->struct_base);
149 }
150 ✗ return ret;
151 }
152
153
154 typedef struct webserver_config_httphandler_class
155 {
156 gate_struct_t struct_base;
157
158 gate_string_t webpath;
159 gate_string_t handlername;
160 } webserver_config_httphandler_t;
161
162 static gate_struct_item_t const webserver_config_httphandler_members[] =
163 {
164 GATE_STRUCT_ITEM(webserver_config_httphandler_t, GATE_TYPE_STRING, webpath),
165 GATE_STRUCT_ITEM(webserver_config_httphandler_t, GATE_TYPE_STRING, handlername),
166 };
167
168 static gate_struct_descriptor_t const webserver_config_httphandler_descriptor =
169 {
170 WEBSERVER_CONFIG_HTTPHANDLER_NAME,
171 webserver_config_httphandler_members,
172 sizeof(webserver_config_httphandler_members) / sizeof(webserver_config_httphandler_members[0]),
173 sizeof(webserver_config_httphandler_t)
174 };
175
176 ✗ static gate_result_t GATE_CALL webserver_config_httphandler_ctor(void* target, void const* src)
177 {
178 gate_result_t ret;
179 ✗ webserver_config_httphandler_t const* ptr_src = (webserver_config_httphandler_t const*)src;
180 ✗ webserver_config_httphandler_t* ptr_dst = (webserver_config_httphandler_t*)target;
181
182 ✗ if (src == NULL)
183 {
184 ✗ ret = gate_struct_init(&ptr_dst->struct_base, &webserver_config_httphandler_descriptor);
185 }
186 else
187 {
188 ✗ gate_mem_clear(ptr_dst, sizeof(webserver_config_httphandler_t));
189 ✗ ret = gate_struct_copy(&ptr_dst->struct_base, &ptr_src->struct_base);
190 }
191 ✗ return ret;
192 }
193
194
195
196 typedef struct webserver_config_webservice_class
197 {
198 gate_struct_t struct_base;
199
200 gate_string_t webpath;
201 gate_string_t service_address;
202 gate_string_t service_method;
203 } webserver_config_webservice_t;
204
205 static gate_struct_item_t const webserver_config_webservice_members[] =
206 {
207 GATE_STRUCT_ITEM(webserver_config_webservice_t, GATE_TYPE_STRING, webpath),
208 GATE_STRUCT_ITEM(webserver_config_webservice_t, GATE_TYPE_STRING, service_address),
209 GATE_STRUCT_ITEM(webserver_config_webservice_t, GATE_TYPE_STRING, service_method),
210 };
211
212 static gate_struct_descriptor_t const webserver_config_webservice_descriptor =
213 {
214 WEBSERVER_CONFIG_VDIR_NAME,
215 webserver_config_webservice_members,
216 sizeof(webserver_config_webservice_members) / sizeof(webserver_config_webservice_members[0]),
217 sizeof(webserver_config_webservice_t)
218 };
219
220 ✗ static gate_result_t GATE_CALL webserver_config_webservice_ctor(void* target, void const* src)
221 {
222 gate_result_t ret;
223 ✗ webserver_config_webservice_t const* ptr_src = (webserver_config_webservice_t const*)src;
224 ✗ webserver_config_webservice_t* ptr_dst = (webserver_config_webservice_t*)target;
225
226 ✗ if (src == NULL)
227 {
228 ✗ ret = gate_struct_init(&ptr_dst->struct_base, &webserver_config_webservice_descriptor);
229 }
230 else
231 {
232 ✗ gate_mem_clear(ptr_dst, sizeof(webserver_config_webservice_t));
233 ✗ ret = gate_struct_copy(&ptr_dst->struct_base, &ptr_src->struct_base);
234 }
235 ✗ return ret;
236 }
237
238
239
240
241 typedef struct webserver_config_class
242 {
243 gate_struct_t struct_base;
244
245 gate_arraylist_t http;
246 gate_arraylist_t https;
247 gate_uint32_t idletimeout;
248 gate_arraylist_t vdirs;
249 gate_arraylist_t httphandlers;
250 gate_arraylist_t webservices;
251 } webserver_config_t;
252
253 static gate_struct_item_t const webserver_config_members[] =
254 {
255 GATE_STRUCT_ITEM(webserver_config_t, GATE_TYPE_ARRAYLIST_STRING, http),
256 GATE_STRUCT_ITEM(webserver_config_t, GATE_TYPE_ARRAYLIST_STRING, https),
257 GATE_STRUCT_ITEM(webserver_config_t, GATE_TYPE_UI32, idletimeout),
258 GATE_STRUCT_ITEM(webserver_config_t, GATE_TYPE_ARRAYLIST_STRUCT, vdirs),
259 GATE_STRUCT_ITEM(webserver_config_t, GATE_TYPE_ARRAYLIST_STRUCT, httphandlers),
260 GATE_STRUCT_ITEM(webserver_config_t, GATE_TYPE_ARRAYLIST_STRUCT, webservices)
261 };
262
263 static gate_struct_descriptor_t const webserver_config_descriptor =
264 {
265 WEBSERVER_CONFIG_NAME,
266 webserver_config_members,
267 sizeof(webserver_config_members) / sizeof(webserver_config_members[0]),
268 sizeof(webserver_config_t)
269 };
270
271 1 static gate_result_t webserver_config_ctor(void* target, void const* src)
272 {
273 gate_result_t ret;
274 1 webserver_config_t const* ptr_src = (webserver_config_t const*)src;
275 1 webserver_config_t* ptr_target = (webserver_config_t*)target;
276
277 do
278 {
279 1 gate_mem_clear(ptr_target, sizeof(webserver_config_t));
280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (src)
281 {
282 ✗ ret = gate_struct_copy(&ptr_target->struct_base, &ptr_src->struct_base);
283 }
284 else
285 {
286 1 ret = gate_struct_init(&ptr_target->struct_base, &webserver_config_descriptor);
287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
288
289 1 ptr_target->vdirs = gate_arraylist_create(sizeof(webserver_config_vdir_t), NULL, 0,
290 &webserver_config_vdir_ctor, &gate_struct_destructor);
291
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_arraylist_is_null(ptr_target->vdirs))
292 {
293 ✗ gate_struct_destructor(ptr_target);
294 ✗ ret = GATE_RESULT_OUTOFMEMORY;
295 ✗ break;
296 }
297
298 1 ptr_target->httphandlers = gate_arraylist_create(sizeof(webserver_config_httphandler_t), NULL, 0,
299 &webserver_config_httphandler_ctor, &gate_struct_destructor);
300
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_arraylist_is_null(ptr_target->httphandlers))
301 {
302 ✗ gate_struct_destructor(ptr_target);
303 ✗ ret = GATE_RESULT_OUTOFMEMORY;
304 ✗ break;
305 }
306
307 1 ptr_target->webservices = gate_arraylist_create(sizeof(webserver_config_webservice_t), NULL, 0,
308 &webserver_config_webservice_ctor, &gate_struct_destructor);
309
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_arraylist_is_null(ptr_target->webservices))
310 {
311 ✗ gate_struct_destructor(ptr_target);
312 ✗ ret = GATE_RESULT_OUTOFMEMORY;
313 ✗ break;
314 }
315 }
316 } while (0);
317
318 1 return ret;
319 }
320
321
322
323
324
325 typedef struct webserver_data_class
326 {
327 gate_httpserver_t server;
328 gate_httpserver_host_id_t hosts[64];
329 gate_size_t hosts_usesd;
330 gate_httpserver_filehandler_config_t file_handlers[16];
331 gate_size_t file_handlers_used;
332 gate_httpserver_handler_t* http_handlers[64];
333 gate_size_t http_handlers_used;
334 gate_httpserver_filehandler_config_t service_handlers[16];
335 gate_size_t service_handlers_used;
336
337 webserver_config_t config;
338 } gate_webserver_data_t;
339
340
341 ✗ static gate_string_t* create_webservice_endpoint(gate_string_t const* ptr_address, gate_string_t const* ptr_method, gate_string_t* ptr_endpoint)
342 {
343 ✗ gate_string_t* ret = NULL;
344 gate_strbuilder_t builder;
345 ✗ gate_strbuilder_create(&builder, gate_string_length(ptr_address) + gate_string_length(ptr_method) + 4);
346 ✗ gate_strbuilder_append_string(&builder, ptr_address);
347 ✗ gate_strbuilder_append_chars(&builder, 1, '/');
348 ✗ gate_strbuilder_append_string(&builder, ptr_method);
349 ✗ ret = gate_strbuilder_to_string(&builder, ptr_endpoint);
350 ✗ gate_strbuilder_release(&builder);
351 ✗ return ret;
352 }
353
354 ✗ static gate_bool_t parse_service_endpoint(gate_string_t const* endpoint, gate_string_t* service_address, gate_string_t* service_endpoint)
355 {
356 gate_size_t pos;
357 ✗ pos = gate_string_char_pos_last(endpoint, '/');
358 ✗ if (pos != GATE_STR_NPOS)
359 {
360 ✗ gate_string_substr(service_address, endpoint, 0, pos);
361 ✗ gate_string_substr(service_endpoint, endpoint, pos + 1, GATE_STR_NPOS);
362 ✗ return true;
363 }
364 ✗ return false;
365 }
366
367 ✗ static gate_result_t GATE_CALL webserver_on_request(gate_httpserver_t* server,
368 gate_httpserver_host_id_t host_id,
369 gate_http_request_t const* request,
370 gate_httpserver_response_t* response,
371 void* userparam)
372 {
373 ✗ gate_result_t ret = GATE_RESULT_NOMATCH;
374 ✗ gate_microservice_base_t* ptr_service = (gate_microservice_base_t*)userparam;
375 ✗ gate_webserver_data_t* ptr_data = (gate_webserver_data_t*)ptr_service->data_ptr;
376 gate_size_t ndx;
377 ✗ gate_string_t service_address = GATE_STRING_INIT_EMPTY;
378 ✗ gate_string_t service_method = GATE_STRING_INIT_EMPTY;
379 gate_microservice_webservice_request_t webrequest;
380 gate_microservice_webservice_response_t webresponse;
381
382 GATE_UNUSED_ARG(server);
383 GATE_UNUSED_ARG(host_id);
384
385 do
386 {
387 /* check if we have a file-handler for the given request */
388 ✗ for (ndx = 0; ndx != ptr_data->file_handlers_used; ++ndx)
389 {
390 ✗ ret = gate_httpserver_filehandler_process(&ptr_data->file_handlers[ndx], request, response);
391 ✗ if (GATE_SUCCEEDED(ret))
392 {
393 ✗ break;
394 }
395 }
396 ✗ if (GATE_SUCCEEDED(ret))
397 {
398 /* file-handler has processed the request, we are done */
399 ✗ break;
400 }
401
402 ✗ for (ndx = 0; ndx != ptr_data->service_handlers_used; ++ndx)
403 {
404 ✗ if (gate_string_starts_with(&request->path, &ptr_data->service_handlers[ndx].http_request_root_path))
405 {
406 ✗ if (parse_service_endpoint(&ptr_data->service_handlers[ndx].filesystem_root_path, &service_address, &service_method))
407 {
408 do
409 {
410 ✗ ret = gate_microservice_webservice_request_ctor(&webrequest, NULL);
411 ✗ GATE_BREAK_IF_FAILED(ret);
412 ✗ ret = gate_microservice_webservice_response_ctor(&webresponse, NULL);
413 ✗ if (GATE_FAILED(ret))
414 {
415 ✗ gate_struct_release(&webrequest.struct_base);
416 ✗ break;
417 }
418 ✗ ret = gate_microhost_remote_invoke(ptr_service->host, &service_address, &service_method, &webrequest.struct_base, &webresponse.struct_base);
419
420 ✗ gate_httpserver_response_set_status(response, 200);
421 ✗ gate_httpserver_response_send_headers(response);
422 ✗ gate_stream_write(response, (char const*)webresponse.content.data, webresponse.content.length, NULL);
423 ✗ gate_stream_flush(response);
424
425 ✗ gate_struct_release(&webresponse.struct_base);
426 ✗ gate_struct_release(&webrequest.struct_base);
427
428 } while (0);
429 ✗ gate_string_release(&service_address);
430 ✗ gate_string_release(&service_method);
431 }
432 else
433 {
434 ✗ ret = GATE_RESULT_FAILED;
435 }
436 ✗ break;
437 }
438 }
439
440 ✗ if (GATE_SUCCEEDED(ret))
441 {
442 /* file-handler has processed the request, we are done */
443 ✗ break;
444 }
445
446 } while (0);
447
448
449
450 ✗ if (GATE_FAILED(ret))
451 {
452 ✗ if (!gate_httpserver_response_are_headers_sent(response))
453 {
454 ✗ gate_httpserver_response_set_status(response, ret == GATE_RESULT_NOMATCH ? 404 : 501);
455 ✗ gate_httpserver_response_send_headers(response);
456 }
457 ✗ gate_stream_flush(response);
458 ✗ ret = GATE_RESULT_OK;
459 }
460
461 ✗ return ret;
462 }
463
464 4 static void release_all_file_handler_configs(gate_httpserver_filehandler_config_t* cfgs, gate_size_t* count)
465 {
466 gate_size_t ndx;
467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 for (ndx = 0; ndx != *count; ++ndx)
468 {
469 ✗ gate_httpserver_filehandler_config_release(&cfgs[ndx]);
470 }
471 4 *count = 0;
472 4 }
473
474 1 static gate_result_t webserver_on_start(gate_microservice_base_t* self)
475 {
476 static gate_string_t const msg_add_host_failed = GATE_STRING_INIT_STATIC("Failed to add host");
477 static gate_string_t const msg_add_host_success = GATE_STRING_INIT_STATIC("Webservice host successfully added");
478 static gate_string_t const msg_no_hosts = GATE_STRING_INIT_STATIC("Webservice contains no configured hosts");
479 static gate_string_t const msg_http_start_failed = GATE_STRING_INIT_STATIC("Failed to start webservice");
480 static gate_string_t const msg_http_start_succeeded = GATE_STRING_INIT_STATIC("Webservice successfully started");
481 gate_result_t ret;
482 1 gate_webserver_data_t* ptr_data = (gate_webserver_data_t*)self->data_ptr;
483 1 gate_httpserver_t* server = &ptr_data->server;
484 gate_httpserver_config_t http_config;
485 gate_httpserver_host_id_t http_host_id;
486 gate_size_t ndx;
487 gate_size_t count;
488 gate_string_t const* ptr_str;
489 webserver_config_vdir_t const* ptr_vdir;
490 webserver_config_webservice_t const* ptr_ws;
491 1 gate_size_t hosts_succeeded = 0;
492 gate_int16_t socket_family;
493 gate_string_t webservice_endpoint;
494
495 do
496 {
497 1 gate_microservice_base_set_condition_bits(self, GATE_MICROSERVICE_CONDITION_INITIALIZING);
498
499 /* export parameters from property storage to native config struct */
500 1 gate_property_export(&self->parameters, GATE_TYPE_STRUCT, &ptr_data->config.struct_base);
501
502 // load HTTP server bindings
503 1 count = gate_arraylist_length(ptr_data->config.http);
504 1 ret = GATE_RESULT_OK;
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (ndx = 0; ndx != count; ++ndx)
506 {
507 ✗ ptr_str = (gate_string_t const*)gate_arraylist_get(ptr_data->config.http, ndx);
508
509 ✗ gate_httpserver_config_init(&http_config);
510
511 ✗ ret = gate_socket_parse_address(ptr_str, &http_config.address, &http_config.port, &socket_family);
512 ✗ GATE_BREAK_IF_FAILED(ret);
513 ✗ http_config.max_connections = 32;
514 ✗ http_config.secure = false;
515
516 ✗ ret = gate_httpserver_add_host(server, &http_config, &webserver_on_request, self, &http_host_id);
517 ✗ gate_httpserver_config_destroy(&http_config);
518 ✗ if (GATE_SUCCEEDED(ret))
519 {
520 ✗ gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_INFO, 0, 0, &self->address, &msg_add_host_success);
521 ✗ ++hosts_succeeded;
522 }
523 else
524 {
525 ✗ gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_WARNING, ret, 0, &self->address, &msg_add_host_failed);
526 }
527 }
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
529
530
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (hosts_succeeded == 0)
531 {
532 1 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_WARNING, 0, 0, &self->address, &msg_no_hosts);
533 }
534
535 // load file-services configuration
536 1 count = gate_arraylist_length(ptr_data->config.vdirs);
537 1 ptr_data->file_handlers_used = 0;
538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (ndx = 0; ndx != count; ++ndx)
539 {
540 ✗ ptr_vdir = (webserver_config_vdir_t const*)gate_arraylist_get(ptr_data->config.vdirs, ndx);
541 ✗ if (!ptr_vdir)
542 {
543 ✗ continue;
544 }
545
546 ✗ ret = gate_httpserver_filehandler_config_init(&ptr_data->file_handlers[ptr_data->file_handlers_used],
547 &ptr_vdir->webpath,
548 &ptr_vdir->filepath,
549 ✗ ptr_vdir->webdav);
550 ✗ if (GATE_SUCCEEDED(ret))
551 {
552 ✗ gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_INFO, 0, 0, &self->address, &ptr_vdir->webpath);
553 ✗ ++ptr_data->file_handlers_used;
554 }
555 else
556 {
557 ✗ gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_WARNING, ret, 0, &self->address, &ptr_vdir->webpath);
558 }
559 }
560
561 // load http-handlers
562 /*
563 count = gate_arraylist_length(ptr_data->config.httphandlers);
564 ptr_data->http_handlers_used = 0;
565 for(ndx = 0; ndx != count; ++ndx)
566 {
567 webserver_config_httphandler_t const* const ptr_handler = (webserver_config_httphandler_t const*)(ptr_data->config.httphandlers, ndx);
568 if(!ptr_handler)
569 {
570 continue;
571 }
572
573 ret
574 }
575 */
576
577 1 count = gate_arraylist_length(ptr_data->config.webservices);
578 1 ptr_data->service_handlers_used = 0;
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (ndx = 0; ndx != count; ++ndx)
580 {
581 ✗ ptr_ws = (webserver_config_webservice_t const*)gate_arraylist_get(ptr_data->config.webservices, ndx);
582 ✗ if (!ptr_ws)
583 {
584 ✗ continue;
585 }
586
587 ✗ if (NULL == create_webservice_endpoint(&ptr_ws->service_address, &ptr_ws->service_method, &webservice_endpoint))
588 {
589 ✗ continue;
590 }
591
592 ✗ ret = gate_httpserver_filehandler_config_init(
593 ✗ &ptr_data->service_handlers[ptr_data->service_handlers_used],
594 &ptr_ws->webpath,
595 &webservice_endpoint,
596 false);
597 ✗ if (GATE_SUCCEEDED(ret))
598 {
599 ✗ ++ptr_data->service_handlers_used;
600 }
601
602 ✗ gate_string_release(&webservice_endpoint);
603 }
604
605 1 ret = gate_httpserver_start(server);
606
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
607 {
608 1 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_INFO, ret, 0, &self->address, &msg_http_start_succeeded);
609 1 count = gate_arraylist_length(ptr_data->config.http);
610
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 gate_microservice_base_set_condition_bits(self, (count == hosts_succeeded)
611 ? GATE_MICROSERVICE_CONDITION_FULL_OPERATIONAL
612 : GATE_MICROSERVICE_CONDITION_PARTIAL_OPERATIONAL
613 );
614 }
615 else
616 {
617 ✗ gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_ERROR, ret, 0, &self->address, &msg_http_start_failed);
618 ✗ gate_microservice_base_set_condition_bits(self, GATE_MICROSERVICE_CONDITION_INIT_ERROR);
619 }
620
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
621 } while (0);
622
623 1 gate_microservice_base_clear_condition_bits(self, GATE_MICROSERVICE_CONDITION_INITIALIZING);
624
625
626
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
627 {
628 ✗ release_all_file_handler_configs(&ptr_data->file_handlers[0], &ptr_data->file_handlers_used);
629 }
630
631 1 return ret;
632 }
633 2 static gate_result_t webserver_on_stop(gate_microservice_base_t* self)
634 {
635 2 gate_result_t ret = GATE_RESULT_OK;
636 2 gate_webserver_data_t* webserver_data = (gate_webserver_data_t*)self->data_ptr;
637 do
638 {
639 2 gate_httpserver_remove_all_hosts(&webserver_data->server);
640 2 gate_httpserver_stop(&webserver_data->server);
641 2 release_all_file_handler_configs(&webserver_data->file_handlers[0], &webserver_data->file_handlers_used);
642 2 release_all_file_handler_configs(&webserver_data->service_handlers[0], &webserver_data->service_handlers_used);
643 } while (0);
644 2 return ret;
645 }
646
647 1 static void webserver_on_release(gate_microservice_base_t* self)
648 {
649 1 gate_webserver_data_t* ptr_data = (gate_webserver_data_t*)self->data_ptr;
650
651 1 webserver_on_stop(self);
652
653 1 gate_httpserver_destroy(&ptr_data->server);
654 1 gate_struct_release(&ptr_data->config.struct_base);
655 1 }
656
657 ✗ static gate_result_t webserver_on_message_received(gate_microservice_base_t* self,
658 gate_string_t const* source, gate_string_t const* destination,
659 gate_string_t const* msg_id, gate_string_t const* message)
660 {
661 ✗ gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
662 GATE_UNUSED_ARG(self);
663 GATE_UNUSED_ARG(source);
664 GATE_UNUSED_ARG(destination);
665 GATE_UNUSED_ARG(msg_id);
666 GATE_UNUSED_ARG(message);
667 ✗ return ret;
668 }
669 ✗ static gate_result_t webserver_on_object_received(gate_microservice_base_t* self,
670 gate_string_t const* source, gate_string_t const* destination,
671 gate_string_t const* obj_id, gate_object_t* obj)
672 {
673 ✗ gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
674 GATE_UNUSED_ARG(self);
675 GATE_UNUSED_ARG(source);
676 GATE_UNUSED_ARG(destination);
677 GATE_UNUSED_ARG(obj_id);
678 GATE_UNUSED_ARG(obj);
679 ✗ return ret;
680 }
681 ✗ static gate_result_t webserver_on_invoke(gate_microservice_base_t* self, gate_string_t const* method,
682 gate_struct_t const* request, gate_struct_t* response)
683 {
684 ✗ gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
685 GATE_UNUSED_ARG(self);
686 GATE_UNUSED_ARG(method);
687 GATE_UNUSED_ARG(request);
688 GATE_UNUSED_ARG(response);
689 ✗ return ret;
690 }
691
692 1 gate_microservice_t* gate_microservice_webserver_create(void)
693 {
694 1 gate_microservice_t* ret = NULL;
695 1 gate_microservice_base_t* webserver_service = NULL;
696 1 gate_webserver_data_t* webserver_data = NULL;
697 gate_result_t result;
698
699 do
700 {
701 1 webserver_service = gate_microservice_base_create(sizeof(gate_webserver_data_t), NULL);
702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == webserver_service)
703 {
704 ✗ break;
705 }
706
707 1 webserver_service->on_release = &webserver_on_release;
708 1 webserver_service->on_start = &webserver_on_start;
709 1 webserver_service->on_stop = &webserver_on_stop;
710 1 webserver_service->on_message_received = &webserver_on_message_received;
711 1 webserver_service->on_object_received = &webserver_on_object_received;
712 1 webserver_service->on_invoke = &webserver_on_invoke;
713
714 /* init webserver internal data */
715 1 webserver_data = (gate_webserver_data_t*)webserver_service->data_ptr;
716
717 1 webserver_config_ctor(&webserver_data->config.struct_base, NULL);
718
719 1 gate_property_create_object(&webserver_service->parameters);
720 1 gate_property_import(&webserver_service->parameters, GATE_TYPE_STRUCT, &webserver_data->config.struct_base);
721 1 webserver_service->ptr_parameters = &webserver_data->config.struct_base;
722
723 1 result = gate_httpserver_create(&webserver_data->server);
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(result);
725
726 1 ret = (gate_microservice_t*)webserver_service;
727 1 webserver_service = NULL;
728
729 } while (0);
730
731
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (webserver_service != NULL)
732 {
733 ✗ gate_object_release(webserver_service);
734 }
735 1 return ret;
736 }
737
738