GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tech/microservices/webserver_service.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 235 0.0%
Functions: 0 17 0.0%
Branches: 0 84 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, 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 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 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 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 static gate_result_t webserver_config_ctor(void* target, void const* src)
272 {
273 gate_result_t ret;
274 webserver_config_t const* ptr_src = (webserver_config_t const*)src;
275 webserver_config_t* ptr_target = (webserver_config_t*)target;
276
277 do
278 {
279 gate_mem_clear(ptr_target, sizeof(webserver_config_t));
280 if (src)
281 {
282 ret = gate_struct_copy(&ptr_target->struct_base, &ptr_src->struct_base);
283 }
284 else
285 {
286 ret = gate_struct_init(&ptr_target->struct_base, &webserver_config_descriptor);
287 GATE_BREAK_IF_FAILED(ret);
288
289 ptr_target->vdirs = gate_arraylist_create(sizeof(webserver_config_vdir_t), NULL, 0,
290 &webserver_config_vdir_ctor, &gate_struct_destructor);
291 if (NULL == ptr_target->vdirs)
292 {
293 gate_struct_destructor(ptr_target);
294 ret = GATE_RESULT_OUTOFMEMORY;
295 break;
296 }
297
298 ptr_target->httphandlers = gate_arraylist_create(sizeof(webserver_config_httphandler_t), NULL, 0,
299 &webserver_config_httphandler_ctor, &gate_struct_destructor);
300 if (NULL == ptr_target->httphandlers)
301 {
302 gate_struct_destructor(ptr_target);
303 ret = GATE_RESULT_OUTOFMEMORY;
304 break;
305 }
306
307 ptr_target->webservices = gate_arraylist_create(sizeof(webserver_config_webservice_t), NULL, 0,
308 &webserver_config_webservice_ctor, &gate_struct_destructor);
309 if (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 return ret;
319 }
320
321
322
323
324
325
326
327
328 typedef struct webserver_data_class
329 {
330 gate_httpserver_t server;
331 gate_httpserver_host_id_t hosts[64];
332 gate_size_t hosts_usesd;
333 gate_httpserver_filehandler_config_t file_handlers[16];
334 gate_size_t file_handlers_used;
335 gate_httpserver_handler_t* http_handlers[64];
336 gate_size_t http_handlers_used;
337 gate_httpserver_filehandler_config_t service_handlers[16];
338 gate_size_t service_handlers_used;
339
340 webserver_config_t config;
341 } gate_webserver_data_t;
342
343
344 static gate_string_t* create_webservice_endpoint(gate_string_t const* ptr_address, gate_string_t const* ptr_method, gate_string_t* ptr_endpoint)
345 {
346 gate_string_t* ret = NULL;
347 gate_strbuilder_t builder;
348 gate_strbuilder_create(&builder, gate_string_length(ptr_address) + gate_string_length(ptr_method) + 4);
349 gate_strbuilder_append_string(&builder, ptr_address);
350 gate_strbuilder_append_chars(&builder, 1, '/');
351 gate_strbuilder_append_string(&builder, ptr_method);
352 ret = gate_strbuilder_to_string(&builder, ptr_endpoint);
353 gate_strbuilder_release(&builder);
354 return ret;
355 }
356
357 static gate_bool_t parse_service_endpoint(gate_string_t const* endpoint, gate_string_t* service_address, gate_string_t* service_endpoint)
358 {
359 gate_size_t pos;
360 pos = gate_string_char_pos_last(endpoint, '/');
361 if (pos != GATE_STR_NPOS)
362 {
363 gate_string_substr(service_address, endpoint, 0, pos);
364 gate_string_substr(service_endpoint, endpoint, pos + 1, GATE_STR_NPOS);
365 return true;
366 }
367 return false;
368 }
369
370 static gate_result_t webserver_on_request(gate_httpserver_t* server,
371 gate_httpserver_host_id_t host_id,
372 gate_http_request_t const* request,
373 gate_httpserver_response_t* response,
374 void* userparam)
375 {
376 gate_result_t ret = GATE_RESULT_NOMATCH;
377 gate_microservice_base_t* ptr_service = (gate_microservice_base_t*)userparam;
378 gate_webserver_data_t* ptr_data = (gate_webserver_data_t*)ptr_service->data_ptr;
379 gate_size_t ndx;
380 gate_string_t service_address = GATE_STRING_INIT_EMPTY;
381 gate_string_t service_method = GATE_STRING_INIT_EMPTY;
382 gate_microservice_webservice_request_t webrequest;
383 gate_microservice_webservice_response_t webresponse;
384
385 GATE_UNUSED_ARG(server);
386
387 do
388 {
389 /* check if we have a file-handler for the given request */
390 for (ndx = 0; ndx != ptr_data->file_handlers_used; ++ndx)
391 {
392 ret = gate_httpserver_filehandler_process(&ptr_data->file_handlers[ndx], request, response);
393 if (GATE_SUCCEEDED(ret))
394 {
395 break;
396 }
397 }
398 if (GATE_SUCCEEDED(ret))
399 {
400 /* file-handler has processed the request, we are done */
401 break;
402 }
403
404 for (ndx = 0; ndx != ptr_data->service_handlers_used; ++ndx)
405 {
406 if (gate_string_starts_with(&request->path, &ptr_data->service_handlers[ndx].http_request_root_path))
407 {
408 if (parse_service_endpoint(&ptr_data->service_handlers[ndx].filesystem_root_path, &service_address, &service_method))
409 {
410 do
411 {
412 ret = gate_microservice_webservice_request_ctor(&webrequest, NULL);
413 GATE_BREAK_IF_FAILED(ret);
414 ret = gate_microservice_webservice_response_ctor(&webresponse, NULL);
415 if (GATE_FAILED(ret))
416 {
417 gate_struct_release(&webrequest.struct_base);
418 break;
419 }
420 ret = gate_microhost_remote_invoke(ptr_service->host, &service_address, &service_method, &webrequest.struct_base, &webresponse.struct_base);
421
422 gate_httpserver_response_set_status(response, 200);
423 gate_httpserver_response_send_headers(response);
424 gate_stream_write(response, (char const*)webresponse.content.data, webresponse.content.length, NULL);
425 gate_stream_flush(response);
426
427 gate_struct_release(&webresponse.struct_base);
428 gate_struct_release(&webrequest.struct_base);
429
430 } while (0);
431 gate_string_release(&service_address);
432 gate_string_release(&service_method);
433 }
434 else
435 {
436 ret = GATE_RESULT_FAILED;
437 }
438 break;
439 }
440 }
441
442 if (GATE_SUCCEEDED(ret))
443 {
444 /* file-handler has processed the request, we are done */
445 break;
446 }
447
448 } while (0);
449
450
451
452 if (GATE_FAILED(ret))
453 {
454 if (!gate_httpserver_response_are_headers_sent(response))
455 {
456 gate_httpserver_response_set_status(response, ret == GATE_RESULT_NOMATCH ? 404 : 501);
457 gate_httpserver_response_send_headers(response);
458 }
459 gate_stream_flush(response);
460 ret = GATE_RESULT_OK;
461 }
462
463 return ret;
464 }
465
466 static void release_all_file_handler_configs(gate_httpserver_filehandler_config_t* cfgs, gate_size_t* count)
467 {
468 gate_size_t ndx;
469 for (ndx = 0; ndx != *count; ++ndx)
470 {
471 gate_httpserver_filehandler_config_release(&cfgs[ndx]);
472 }
473 *count = 0;
474 }
475
476 static gate_result_t webserver_on_start(gate_microservice_base_t* self)
477 {
478 static gate_string_t const msg_add_host_failed = GATE_STRING_INIT_STATIC("Failed to add host");
479 static gate_string_t const msg_add_host_success = GATE_STRING_INIT_STATIC("Webservice host successfully added");
480 static gate_string_t const msg_no_hosts = GATE_STRING_INIT_STATIC("Webservice contains no configured hosts");
481 static gate_string_t const msg_http_start_failed = GATE_STRING_INIT_STATIC("Failed to start webservice");
482 static gate_string_t const msg_http_start_succeeded = GATE_STRING_INIT_STATIC("Webservice successfully started");
483 gate_result_t ret = GATE_RESULT_FAILED;
484 gate_webserver_data_t* ptr_data = (gate_webserver_data_t*)self->data_ptr;
485 gate_httpserver_t* server = &ptr_data->server;
486 gate_httpserver_config_t http_config;
487 gate_httpserver_host_id_t http_host_id;
488 gate_size_t ndx;
489 gate_size_t count;
490 gate_string_t const* ptr_str;
491 webserver_config_vdir_t const* ptr_vdir;
492 webserver_config_webservice_t const* ptr_ws;
493 gate_size_t hosts_succeeded = 0;
494 gate_int16_t socket_family;
495 gate_string_t webservice_endpoint;
496
497 do
498 {
499 gate_microservice_base_set_condition_bits(self, GATE_MICROSERVICE_CONDITION_INITIALIZING);
500
501 /* export parameters from property storage to native config struct */
502 gate_property_export(&self->parameters, GATE_TYPE_STRUCT, &ptr_data->config.struct_base);
503
504 // load HTTP server bindings
505 count = gate_arraylist_length(ptr_data->config.http);
506 ret = GATE_RESULT_OK;
507 for (ndx = 0; ndx != count; ++ndx)
508 {
509 ptr_str = (gate_string_t const*)gate_arraylist_get(ptr_data->config.http, ndx);
510
511 gate_httpserver_config_init(&http_config);
512
513 ret = gate_socket_parse_address(ptr_str, &http_config.address, &http_config.port, &socket_family);
514 GATE_BREAK_IF_FAILED(ret);
515 http_config.max_connections = 32;
516 http_config.secure = false;
517
518 ret = gate_httpserver_add_host(server, &http_config, &webserver_on_request, self, &http_host_id);
519 gate_httpserver_config_destroy(&http_config);
520 if (GATE_SUCCEEDED(ret))
521 {
522 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_INFO, 0, 0, &self->address, &msg_add_host_success);
523 ++hosts_succeeded;
524 }
525 else
526 {
527 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_WARNING, ret, 0, &self->address, &msg_add_host_failed);
528 }
529 }
530
531 if (hosts_succeeded == 0)
532 {
533 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_WARNING, 0, 0, &self->address, &msg_no_hosts);
534 }
535
536 // load file-services configuration
537 count = gate_arraylist_length(ptr_data->config.vdirs);
538 ptr_data->file_handlers_used = 0;
539 for (ndx = 0; ndx != count; ++ndx)
540 {
541 ptr_vdir = (webserver_config_vdir_t const*)gate_arraylist_get(ptr_data->config.vdirs, ndx);
542 if (!ptr_vdir)
543 {
544 continue;
545 }
546
547 ret = gate_httpserver_filehandler_config_init(&ptr_data->file_handlers[ptr_data->file_handlers_used],
548 &ptr_vdir->webpath,
549 &ptr_vdir->filepath,
550 ptr_vdir->webdav);
551 if (GATE_SUCCEEDED(ret))
552 {
553 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_INFO, 0, 0, &self->address, &ptr_vdir->webpath);
554 ++ptr_data->file_handlers_used;
555 }
556 else
557 {
558 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_WARNING, ret, 0, &self->address, &ptr_vdir->webpath);
559 }
560 }
561
562 // load http-handlers
563 /*
564 count = gate_arraylist_length(ptr_data->config.httphandlers);
565 ptr_data->http_handlers_used = 0;
566 for(ndx = 0; ndx != count; ++ndx)
567 {
568 webserver_config_httphandler_t const* const ptr_handler = (webserver_config_httphandler_t const*)(ptr_data->config.httphandlers, ndx);
569 if(!ptr_handler)
570 {
571 continue;
572 }
573
574 ret
575 }
576 */
577
578 count = gate_arraylist_length(ptr_data->config.webservices);
579 ptr_data->service_handlers_used = 0;
580 for (ndx = 0; ndx != count; ++ndx)
581 {
582 ptr_ws = (webserver_config_webservice_t const*)gate_arraylist_get(ptr_data->config.webservices, ndx);
583 if (!ptr_ws)
584 {
585 continue;
586 }
587
588 if (NULL == create_webservice_endpoint(&ptr_ws->service_address, &ptr_ws->service_method, &webservice_endpoint))
589 {
590 continue;
591 }
592
593 ret = gate_httpserver_filehandler_config_init(
594 &ptr_data->service_handlers[ptr_data->service_handlers_used],
595 &ptr_ws->webpath,
596 &webservice_endpoint,
597 false);
598 if (GATE_SUCCEEDED(ret))
599 {
600 ++ptr_data->service_handlers_used;
601 }
602
603 gate_string_release(&webservice_endpoint);
604 }
605
606 ret = gate_httpserver_start(server);
607 if (GATE_SUCCEEDED(ret))
608 {
609 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_INFO, ret, 0, &self->address, &msg_http_start_succeeded);
610 count = gate_arraylist_length(ptr_data->config.http);
611 gate_microservice_base_set_condition_bits(self, (count == hosts_succeeded)
612 ? GATE_MICROSERVICE_CONDITION_FULL_OPERATIONAL
613 : GATE_MICROSERVICE_CONDITION_PARTIAL_OPERATIONAL
614 );
615 }
616 else
617 {
618 gate_microhost_log(self->host, GATE_MICROSERVICE_LOGTYPE_ERROR, ret, 0, &self->address, &msg_http_start_failed);
619 gate_microservice_base_set_condition_bits(self, GATE_MICROSERVICE_CONDITION_INIT_ERROR);
620 }
621 GATE_BREAK_IF_FAILED(ret);
622 } while (0);
623
624 gate_microservice_base_clear_condition_bits(self, GATE_MICROSERVICE_CONDITION_INITIALIZING);
625
626
627 if (GATE_FAILED(ret))
628 {
629 release_all_file_handler_configs(&ptr_data->file_handlers[0], &ptr_data->file_handlers_used);
630 }
631
632 return ret;
633 }
634 static gate_result_t webserver_on_stop(gate_microservice_base_t* self)
635 {
636 gate_result_t ret = GATE_RESULT_OK;
637 gate_webserver_data_t* webserver_data = (gate_webserver_data_t*)self->data_ptr;
638 do
639 {
640 gate_httpserver_remove_all_hosts(&webserver_data->server);
641 gate_httpserver_stop(&webserver_data->server);
642 release_all_file_handler_configs(&webserver_data->file_handlers[0], &webserver_data->file_handlers_used);
643 release_all_file_handler_configs(&webserver_data->service_handlers[0], &webserver_data->service_handlers_used);
644 } while (0);
645 return ret;
646 }
647
648 static void webserver_on_release(gate_microservice_base_t* self)
649 {
650 gate_webserver_data_t* ptr_data = (gate_webserver_data_t*)self->data_ptr;
651
652 webserver_on_stop(self);
653
654 gate_httpserver_destroy(&ptr_data->server);
655 gate_struct_release(&ptr_data->config.struct_base);
656 }
657
658 static gate_result_t webserver_on_message_received(gate_microservice_base_t* self,
659 gate_string_t const* source, gate_string_t const* destination,
660 gate_string_t const* msg_id, gate_string_t const* message)
661 {
662 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
663 GATE_UNUSED_ARG(self);
664 GATE_UNUSED_ARG(source);
665 GATE_UNUSED_ARG(destination);
666 GATE_UNUSED_ARG(msg_id);
667 GATE_UNUSED_ARG(message);
668 return ret;
669 }
670 static gate_result_t webserver_on_object_received(gate_microservice_base_t* self,
671 gate_string_t const* source, gate_string_t const* destination,
672 gate_string_t const* obj_id, gate_object_t* obj)
673 {
674 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
675 GATE_UNUSED_ARG(self);
676 GATE_UNUSED_ARG(source);
677 GATE_UNUSED_ARG(destination);
678 GATE_UNUSED_ARG(obj_id);
679 GATE_UNUSED_ARG(obj);
680 return ret;
681 }
682 static gate_result_t webserver_on_invoke(gate_microservice_base_t* self, gate_string_t const* method,
683 gate_struct_t const* request, gate_struct_t* response)
684 {
685 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
686 GATE_UNUSED_ARG(self);
687 GATE_UNUSED_ARG(method);
688 GATE_UNUSED_ARG(request);
689 GATE_UNUSED_ARG(response);
690 return ret;
691 }
692
693 gate_microservice_t* gate_microservice_webserver_create()
694 {
695 gate_microservice_t* ret = NULL;
696 gate_microservice_base_t* webserver_service = NULL;
697 gate_webserver_data_t* webserver_data = NULL;
698 gate_result_t result;
699
700 do
701 {
702 webserver_service = gate_microservice_base_create(sizeof(gate_webserver_data_t), NULL);
703 if (NULL == webserver_service)
704 {
705 break;
706 }
707
708 webserver_service->on_release = &webserver_on_release;
709 webserver_service->on_start = &webserver_on_start;
710 webserver_service->on_stop = &webserver_on_stop;
711 webserver_service->on_message_received = &webserver_on_message_received;
712 webserver_service->on_object_received = &webserver_on_object_received;
713 webserver_service->on_invoke = &webserver_on_invoke;
714
715 /* init webserver internal data */
716 webserver_data = (gate_webserver_data_t*)webserver_service->data_ptr;
717
718 webserver_config_ctor(&webserver_data->config.struct_base, NULL);
719
720 gate_property_create_object(&webserver_service->parameters);
721 gate_property_import(&webserver_service->parameters, GATE_TYPE_STRUCT, &webserver_data->config.struct_base);
722 webserver_service->ptr_parameters = &webserver_data->config.struct_base;
723
724 result = gate_httpserver_create(&webserver_data->server);
725 GATE_BREAK_IF_FAILED(result);
726
727 ret = (gate_microservice_t*)webserver_service;
728 webserver_service = NULL;
729
730 } while (0);
731
732 if (webserver_service != NULL)
733 {
734 gate_object_release(webserver_service);
735 }
736 return ret;
737 }
738
739