2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
42#ifndef APPS_HTTP_MODEL_CLIENTS_H
43#define APPS_HTTP_MODEL_CLIENTS_H
46#define STR_INCLUDE(a) #a
51#define EVENTSOURCE_INCLUDE QUOTE_INCLUDE(web/http/STREAM/NET/EventSource.h)
55#include CLIENT_INCLUDE
56#include EVENTSOURCE_INCLUDE
58#ifndef DOXYGEN_SHOULD_SKIP_THIS
60#include "log/Logger.h"
61#include "web/http/http_utils.h"
63#if (STREAM_TYPE == TLS)
65#include <openssl/ssl.h>
66#include <openssl/x509v3.h>
71static void logResponse(
const std::shared_ptr<web::http::client::Request>& req,
const std::shared_ptr<web::http::client::Response>& res) {
72 VLOG(1) << req->getSocketContext()->getSocketConnection()->getConnectionName() <<
" HTTP response: " << req->method <<
" " << req->url
73 <<
" HTTP/" << req->httpMajor <<
"." << req->httpMinor <<
"\n"
74 << httputils::toString(req->method,
76 "HTTP/" + std::to_string(req->httpMajor) +
"." + std::to_string(req->httpMinor),
83 << httputils::toString(res->httpVersion, res->statusCode, res->reason, res->headers, res->cookies, res->body);
86#if (STREAM_TYPE == LEGACY)
99 [](
const std::shared_ptr<MasterRequest>& req) {
100 VLOG(1) << req->getSocketContext()->getSocketConnection()->getConnectionName() <<
": OnRequestStart";
105 req->set(
"Connection",
"keep-alive");
106 req->setTrailer(
"MyTrailer",
110 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
111 logResponse(req, res);
113 [](
const std::shared_ptr<Request>&,
const std::string&) {
118 req->url =
"/sendfile/";
119 req->set(
"Connection",
"keep-alive");
121 "/home/voc/projects/snodec/snode.c/CMakeLists.tt",
124 VLOG(1) << req->getSocketContext()->getSocketConnection()->getConnectionName()
125 <<
" HTTP: Request accepted: GET / HTTP/" << req->httpMajor <<
"." << req->httpMinor;
126 VLOG(1) <<
" /home/voc/projects/snodec/snode.c/CMakeLists.tt";
128 LOG(ERROR) << req->getSocketContext()->getSocketConnection()->getConnectionName()
129 <<
" HTTP: Request failed: GET / HTTP/" << req->httpMajor <<
"." << req->httpMinor;
130 PLOG(ERROR) <<
" /home/voc/projects/snodec/snode.c/CMakeLists.tt";
133 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
134 logResponse(req, res);
136 [](
const std::shared_ptr<Request>&,
const std::string&) {
142 req->set(
"Connection",
"keep-alive");
143 req->setTrailer(
"MyTrailer",
147 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
148 logResponse(req, res);
150 [](
const std::shared_ptr<Request>&,
const std::string&) {
156 req->set(
"Connection",
"keep-alive");
158 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
159 logResponse(req, res);
161 [](
const std::shared_ptr<Request>&,
const std::string&) {
165 req->url =
"/index.html";
168 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
169 logResponse(req, res);
171 [](
const std::shared_ptr<Request>&,
const std::string&) {
174 req->set(
"Connection",
"keep-alive");
176 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
177 logResponse(req, res);
179 [req](
const std::shared_ptr<Request>&,
const std::string&) {
181 req->url =
"/index.html";
182 req->set(
"Connection",
"keep-alive");
184 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
185 logResponse(req, res);
187 [req](
const std::shared_ptr<Request>&,
const std::string&) {
190 req->set(
"Connection",
"keep-alive");
192 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
193 logResponse(req, res);
195 [req](
const std::shared_ptr<Request>&,
const std::string&) {
197 req->url =
"/index.html";
198 req->set(
"Connection",
"keep-alive");
200 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
201 logResponse(req, res);
203 [req](
const std::shared_ptr<Request>&,
const std::string&) {
206 req->set(
"Connection",
"keep-alive");
208 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
209 logResponse(req, res);
211 [req](
const std::shared_ptr<Request>&,
const std::string&) {
213 req->url =
"/index.html";
214 req->set(
"Connection",
"keep-alive");
216 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
217 logResponse(req, res);
219 [req](
const std::shared_ptr<Request>&,
const std::string&) {
222 req->set(
"Connection",
"keep-alive");
224 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
225 logResponse(req, res);
227 [req](
const std::shared_ptr<Request>&,
const std::string&) {
229 req->url =
"/index.html";
230 req->set(
"Connection",
"keep-alive");
232 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
233 logResponse(req, res);
235 [req](
const std::shared_ptr<Request>&,
const std::string&) {
238 req->set(
"Connection",
"keep-alive");
240 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
241 logResponse(req, res);
243 [req](
const std::shared_ptr<Request>&,
const std::string&) {
245 req->url =
"/index.html";
246 req->set(
"Connection",
"keep-alive");
248 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
249 logResponse(req, res);
251 [req](
const std::shared_ptr<Request>&,
const std::string&) {
254 req->set(
"Connection",
"keep-alive");
256 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
257 logResponse(req, res);
259 [req](
const std::shared_ptr<Request>&,
const std::string&) {
261 req->url =
"/index.html";
262 req->set(
"Connection",
"keep-alive");
264 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
265 logResponse(req, res);
267 [req](
const std::shared_ptr<Request>&,
const std::string&) {
270 req->set(
"Connection",
"keep-alive");
272 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
273 logResponse(req, res);
275 [req](
const std::shared_ptr<Request>&,
const std::string&) {
277 req->url =
"/index.html";
278 req->set(
"Connection",
"keep-alive");
280 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
281 logResponse(req, res);
283 [req](
const std::shared_ptr<Request>&,
const std::string&) {
286 req->set(
"Connection",
"keep-alive");
288 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
289 logResponse(req, res);
291 [req](
const std::shared_ptr<Request>&,
const std::string&) {
295
296
297
299
300
301
303
304
305
307 const std::shared_ptr<web::http::client::tools::EventSource> eventStream_1 =
308 web::http::legacy::NET::EventSource(
"http://" + req->hostFieldValue,
"/sse?hihi=3");
311 eventStream_1->onOpen([]() {
312 VLOG(0) <<
"OnOpen 1";
315 eventStream_1->onError([]() {
316 VLOG(0) <<
"onError 1";
319 eventStream_1->onMessage([](
const web::http::client::tools::EventSource::MessageEvent& message) {
320 VLOG(0) <<
"OnMessage 1:1: " << message.data;
322 eventStream_1->onMessage([](
const web::http::client::tools::EventSource::MessageEvent& message) {
323 VLOG(0) <<
"OnMessage 1:2: " << message.data;
325 eventStream_1->addEventListener(
"myevent", [](
const web::http::client::tools::EventSource::MessageEvent& message) {
326 VLOG(0) <<
"EventListener for 'myevent' 1:1: " << message.lastEventId <<
" : " << message.data;
328 eventStream_1->addEventListener(
"myevent", [](
const web::http::client::tools::EventSource::MessageEvent& message) {
329 VLOG(0) <<
"EventListener for 'myevent' 1:2: " << message.lastEventId <<
" : " << message.data;
332 core::timer::Timer::singleshotTimer(
334 eventStream_1->close();
339 auto eventStream_2 = web::http::legacy::NET::EventSource(
"http://localhost:8080/sse");
342 eventStream_2->onOpen([]() {
343 VLOG(0) <<
"OnOpen 2";
346 eventStream_2->onError([]() {
347 VLOG(0) <<
"onError 2";
350 eventStream_2->onMessage([](
const web::http::client::tools::EventSource::MessageEvent& message) {
351 VLOG(0) <<
"OnMessage 2:1: " << message.data;
353 eventStream_2->onMessage([](
const web::http::client::tools::EventSource::MessageEvent& message) {
354 VLOG(0) <<
"OnMessage 2:2: " << message.data;
356 eventStream_2->addEventListener(
"myevent", [](
const web::http::client::tools::EventSource::MessageEvent& message) {
357 VLOG(0) <<
"EventListener for 'myevent' 2:1: " << message.lastEventId <<
" : " << message.data;
359 eventStream_2->addEventListener(
"myevent", [](
const web::http::client::tools::EventSource::MessageEvent& message) {
360 VLOG(0) <<
"EventListener for 'myevent' 2:2: " << message.lastEventId <<
" : " << message.data;
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
502 []([[maybe_unused]]
const std::shared_ptr<Request>& req) {
503 VLOG(1) << req->getSocketContext()->getSocketConnection()->getConnectionName() <<
": OnRequestEnd";
506 client.setOnConnect([](SocketConnection* socketConnection) {
507 VLOG(1) << socketConnection->getConnectionName() <<
": OnConnect";
509 VLOG(1) <<
"\tLocal: " << socketConnection->getLocalAddress().toString();
510 VLOG(1) <<
"\tPeer: " << socketConnection->getRemoteAddress().toString();
513 client.setOnDisconnect([](SocketConnection* socketConnection) {
514 VLOG(1) << socketConnection->getConnectionName() <<
": OnDisconnect";
516 VLOG(1) <<
"\tLocal: " << socketConnection->getLocalAddress().toString();
517 VLOG(1) <<
"\tPeer: " << socketConnection->getRemoteAddress().toString();
527#if (STREAM_TYPE == TLS)
529namespace apps::http::
tls {
540 [](
const std::shared_ptr<MasterRequest>& req) {
541 VLOG(1) << req->getSocketContext()->getSocketConnection()->getConnectionName() <<
": OnRequestStart";
544 req->set(
"Connection",
"keep-alive");
546 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
547 logResponse(req, res);
549 [](
const std::shared_ptr<Request>&,
const std::string&) {
552 req->set(
"Connection",
"keep-alive");
554 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
555 logResponse(req, res);
557 [](
const std::shared_ptr<Request>&,
const std::string&) {
559 req->url =
"/index.html";
560 req->set(
"Connection",
"keep-alive");
562 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
563 logResponse(req, res);
565 [](
const std::shared_ptr<Request>&,
const std::string&) {
568 req->set(
"Connection",
"keep-alive");
570 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
571 logResponse(req, res);
573 [](
const std::shared_ptr<Request>&,
const std::string&) {
575 req->url =
"/index.html";
576 req->set(
"Connection",
"keep-alive");
578 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
579 logResponse(req, res);
581 [](
const std::shared_ptr<Request>&,
const std::string&) {
584 req->set(
"Connection",
"keep-alive");
586 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
587 logResponse(req, res);
589 [](
const std::shared_ptr<Request>&,
const std::string&) {
591 req->url =
"/index.html";
592 req->set(
"Connection",
"keep-alive");
594 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
595 logResponse(req, res);
597 [](
const std::shared_ptr<Request>&,
const std::string&) {
600 req->set(
"Connection",
"keep-alive");
602 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
603 logResponse(req, res);
605 [](
const std::shared_ptr<Request>&,
const std::string&) {
607 req->url =
"/index.html";
608 req->set(
"Connection",
"keep-alive");
610 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
611 logResponse(req, res);
613 [](
const std::shared_ptr<Request>&,
const std::string&) {
616 req->set(
"Connection",
"keep-alive");
618 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
619 logResponse(req, res);
621 [](
const std::shared_ptr<Request>&,
const std::string&) {
623 req->url =
"/index.html";
624 req->set(
"Connection",
"keep-alive");
626 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
627 logResponse(req, res);
629 [](
const std::shared_ptr<Request>&,
const std::string&) {
632 req->set(
"Connection",
"keep-alive");
634 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
635 logResponse(req, res);
637 [](
const std::shared_ptr<Request>&,
const std::string&) {
639 req->url =
"/index.html";
640 req->set(
"Connection",
"keep-alive");
642 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
643 logResponse(req, res);
645 [](
const std::shared_ptr<Request>&,
const std::string&) {
648 req->set(
"Connection",
"keep-alive");
650 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
651 logResponse(req, res);
653 [](
const std::shared_ptr<Request>&,
const std::string&) {
655 req->url =
"/index.html";
656 req->set(
"Connection",
"keep-alive");
658 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
659 logResponse(req, res);
661 [](
const std::shared_ptr<Request>&,
const std::string&) {
664 req->set(
"Connection",
"keep-alive");
666 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
667 logResponse(req, res);
669 [](
const std::shared_ptr<Request>&,
const std::string&) {
671 req->url =
"/index.html";
672 req->set(
"Connection",
"keep-alive");
674 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
675 logResponse(req, res);
677 [](
const std::shared_ptr<Request>&,
const std::string&) {
680 req->set(
"Connection",
"close");
682 [](
const std::shared_ptr<Request>& req,
const std::shared_ptr<Response>& res) {
683 logResponse(req, res);
685 [](
const std::shared_ptr<Request>&,
const std::string&) {
688 []([[maybe_unused]]
const std::shared_ptr<Request>& req) {
689 VLOG(1) << req->getSocketContext()->getSocketConnection()->getConnectionName() <<
": OnRequestEnd";
692 client.setOnConnect([](SocketConnection* socketConnection) {
693 VLOG(1) <<
"OnConnect " << socketConnection->getConnectionName();
695 VLOG(1) <<
"\tLocal: " << socketConnection->getLocalAddress().toString();
696 VLOG(1) <<
"\tPeer: " << socketConnection->getRemoteAddress().toString();
708 client.setOnConnected([](SocketConnection* socketConnection) {
709 VLOG(1) << socketConnection->getConnectionName() <<
": OnConnected";
710 X509* server_cert = SSL_get_peer_certificate(socketConnection->getSSL());
711 if (server_cert !=
nullptr) {
712 long verifyErr = SSL_get_verify_result(socketConnection->getSSL());
714 VLOG(1) <<
"\tPeer certificate verifyErr = " + std::to_string(verifyErr) +
": " +
715 std::string(X509_verify_cert_error_string(verifyErr));
717 char* str = X509_NAME_oneline(X509_get_subject_name(server_cert),
nullptr, 0);
718 VLOG(1) <<
"\t Subject: " + std::string(str);
721 str = X509_NAME_oneline(X509_get_issuer_name(server_cert),
nullptr, 0);
722 VLOG(1) <<
"\t Issuer: " + std::string(str);
727 GENERAL_NAMES* subjectAltNames =
728 static_cast<GENERAL_NAMES*>(X509_get_ext_d2i(server_cert, NID_subject_alt_name,
nullptr,
nullptr));
730#pragma GCC diagnostic push
732#if __has_warning
("-Wused-but-marked-unused")
733#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
737 int32_t altNameCount = sk_GENERAL_NAME_num(subjectAltNames);
739#pragma GCC diagnostic pop
741 VLOG(1) <<
"\t Subject alternative name count: " << altNameCount;
742 for (int32_t i = 0; i < altNameCount; ++i) {
744#pragma GCC diagnostic push
746#if __has_warning
("-Wused-but-marked-unused")
747#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
751 GENERAL_NAME* generalName = sk_GENERAL_NAME_value(subjectAltNames, i);
753#pragma GCC diagnostic pop
755 if (generalName->type == GEN_URI) {
756 std::string subjectAltName =
757 std::string(
reinterpret_cast<
const char*>(ASN1_STRING_get0_data(generalName->d.uniformResourceIdentifier)),
758 static_cast<std::size_t>(ASN1_STRING_length(generalName->d.uniformResourceIdentifier)));
759 VLOG(1) <<
"\t SAN (URI): '" + subjectAltName;
760 }
else if (generalName->type == GEN_DNS) {
761 std::string subjectAltName =
762 std::string(
reinterpret_cast<
const char*>(ASN1_STRING_get0_data(generalName->d.dNSName)),
763 static_cast<std::size_t>(ASN1_STRING_length(generalName->d.dNSName)));
764 VLOG(1) <<
"\t SAN (DNS): '" + subjectAltName;
766 VLOG(1) <<
"\t SAN (Type): '" + std::to_string(generalName->type);
770#pragma GCC diagnostic push
772#if __has_warning
("-Wused-but-marked-unused")
773#pragma GCC diagnostic ignored "-Wused-but-marked-unused"
777 sk_GENERAL_NAME_pop_free(subjectAltNames, GENERAL_NAME_free);
779#pragma GCC diagnostic pop
781 X509_free(server_cert);
783 VLOG(1) <<
"\tPeer certificate: no certificate";
787 client.setOnDisconnect([](SocketConnection* socketConnection) {
788 VLOG(1) << socketConnection->getConnectionName() <<
": OnDisconnect";
790 VLOG(1) <<
"\tLocal: " << socketConnection->getLocalAddress().toString();
791 VLOG(1) <<
"\tPeer: " << socketConnection->getRemoteAddress().toString();
static void logResponse(const std::shared_ptr< web::http::client::Request > &req, const std::shared_ptr< web::http::client::Response > &res)
int main(int argc, char *argv[])