@@ -466,6 +466,178 @@ void test_http_add_proxy_auth_header()
466466 test_ctx_destroy (ctx );
467467}
468468
469+ /* Helper function to verify Host header value */
470+ static void check_host_header (struct flb_http_client * c , const char * expected )
471+ {
472+ flb_sds_t ret_str = flb_http_get_header (c , "Host" , 4 );
473+ if (!TEST_CHECK (ret_str != NULL )) {
474+ TEST_MSG ("flb_http_get_header failed" );
475+ exit (EXIT_FAILURE );
476+ }
477+
478+ if (!TEST_CHECK (flb_sds_cmp (ret_str , expected , strlen (expected )) == 0 )) {
479+ TEST_MSG ("strcmp failed. got=%s expect=%s" , ret_str , expected );
480+ }
481+
482+ flb_sds_destroy (ret_str );
483+ }
484+
485+ /* Helper to test basic host header formatting */
486+ static void test_host_header_format (const char * host , int port , const char * expected )
487+ {
488+ struct test_ctx * ctx = test_ctx_create ();
489+ if (!TEST_CHECK (ctx != NULL )) {
490+ exit (EXIT_FAILURE );
491+ }
492+
493+ struct flb_http_client * c = flb_http_client (ctx -> u_conn , FLB_HTTP_GET , "/" ,
494+ NULL , 0 , host , port , NULL , 0 );
495+ if (!TEST_CHECK (c != NULL )) {
496+ TEST_MSG ("flb_http_client failed" );
497+ test_ctx_destroy (ctx );
498+ exit (EXIT_FAILURE );
499+ }
500+
501+ check_host_header (c , expected );
502+ flb_http_client_destroy (c );
503+ test_ctx_destroy (ctx );
504+ }
505+
506+ /* Helper to test TLS host header formatting */
507+ static void test_tls_host_header_format (const char * host , int port , const char * expected )
508+ {
509+ struct test_ctx * ctx = test_ctx_create ();
510+ if (!TEST_CHECK (ctx != NULL )) {
511+ exit (EXIT_FAILURE );
512+ }
513+
514+ struct flb_upstream * u_tls = flb_upstream_create (ctx -> config , host , port , FLB_IO_TLS , NULL );
515+ if (!TEST_CHECK (u_tls != NULL )) {
516+ TEST_MSG ("flb_upstream_create failed" );
517+ test_ctx_destroy (ctx );
518+ exit (EXIT_FAILURE );
519+ }
520+
521+ struct flb_connection * u_conn_tls = flb_calloc (1 , sizeof (struct flb_connection ));
522+ if (!TEST_CHECK (u_conn_tls != NULL )) {
523+ TEST_MSG ("flb_calloc failed" );
524+ flb_upstream_destroy (u_tls );
525+ test_ctx_destroy (ctx );
526+ exit (EXIT_FAILURE );
527+ }
528+ u_conn_tls -> upstream = u_tls ;
529+
530+ struct flb_http_client * c = flb_http_client (u_conn_tls , FLB_HTTP_GET , "/" ,
531+ NULL , 0 , host , port , NULL , 0 );
532+ if (!TEST_CHECK (c != NULL )) {
533+ TEST_MSG ("flb_http_client failed" );
534+ flb_free (u_conn_tls );
535+ flb_upstream_destroy (u_tls );
536+ test_ctx_destroy (ctx );
537+ exit (EXIT_FAILURE );
538+ }
539+
540+ check_host_header (c , expected );
541+ flb_http_client_destroy (c );
542+ flb_free (u_conn_tls );
543+ flb_upstream_destroy (u_tls );
544+ test_ctx_destroy (ctx );
545+ }
546+
547+ void test_http_ipv6_host_header ()
548+ {
549+ test_host_header_format ("::1" , 8080 , "[::1]:8080" );
550+ }
551+
552+ void test_http_ipv6_bracketed_host_header ()
553+ {
554+ test_host_header_format ("[::1]" , 8080 , "[::1]:8080" );
555+ }
556+
557+ void test_http_ipv4_host_header ()
558+ {
559+ test_host_header_format ("192.168.1.1" , 8080 , "192.168.1.1:8080" );
560+ }
561+
562+ void test_http_domain_host_header ()
563+ {
564+ test_host_header_format ("example.com" , 8080 , "example.com:8080" );
565+ }
566+
567+ void test_https_default_port_host_header ()
568+ {
569+ test_tls_host_header_format ("example.com" , 443 , "example.com" );
570+ }
571+
572+ /* Test various IPv6 address formats */
573+ void test_ipv6_formats_host_header ()
574+ {
575+ size_t index ;
576+ struct {
577+ const char * input ;
578+ const char * expected ;
579+ } test_cases [] = {
580+ {"2001:db8::1" , "[2001:db8::1]:8080" },
581+ {"2001:0db8:0000:0000:0000:0000:0000:0001" , "[2001:0db8:0000:0000:0000:0000:0000:0001]:8080" },
582+ {"::ffff:192.0.2.1" , "[::ffff:192.0.2.1]:8080" },
583+ {"fe80::1" , "[fe80::1]:8080" },
584+ {"::1" , "[::1]:8080" },
585+ {"::" , "[::]:8080" },
586+ {NULL , NULL }
587+ };
588+
589+ for (index = 0 ; test_cases [index ].input != NULL ; index ++ ) {
590+ test_host_header_format (test_cases [index ].input , 8080 , test_cases [index ].expected );
591+ }
592+ }
593+
594+ void test_http_port_80_host_header ()
595+ {
596+ test_host_header_format ("example.com" , 80 , "example.com:80" );
597+ }
598+
599+ void test_port_443_without_tls_host_header ()
600+ {
601+ test_host_header_format ("example.com" , 443 , "example.com:443" );
602+ }
603+
604+ void test_ipv6_zone_id_host_header ()
605+ {
606+ test_host_header_format ("fe80::1%eth0" , 8080 , "[fe80::1]:8080" );
607+ }
608+
609+ void test_https_non_standard_port_host_header ()
610+ {
611+ test_tls_host_header_format ("example.com" , 8443 , "example.com:8443" );
612+ }
613+
614+ void test_ipv6_bracketed_zone_id_host_header ()
615+ {
616+ /* Already bracketed input - zone ID detection only works on unbracketed addresses,
617+ * so this passes through as-is. In practice, bracketed input shouldn't have zone IDs. */
618+ test_host_header_format ("[fe80::1%eth0]" , 8080 , "[fe80::1%eth0]:8080" );
619+ }
620+
621+ void test_https_ipv6_default_port_host_header ()
622+ {
623+ test_tls_host_header_format ("::1" , 443 , "[::1]" );
624+ }
625+
626+ void test_https_ipv6_non_standard_port_host_header ()
627+ {
628+ test_tls_host_header_format ("::1" , 8443 , "[::1]:8443" );
629+ }
630+
631+ void test_https_ipv6_zone_id_default_port_host_header ()
632+ {
633+ test_tls_host_header_format ("fe80::1%eth0" , 443 , "[fe80::1]" );
634+ }
635+
636+ void test_https_ipv6_zone_id_non_standard_port_host_header ()
637+ {
638+ test_tls_host_header_format ("fe80::1%eth0" , 8443 , "[fe80::1]:8443" );
639+ }
640+
469641TEST_LIST = {
470642 { "http_buffer_increase" , test_http_buffer_increase },
471643 { "add_get_header" , test_http_add_get_header },
@@ -474,5 +646,20 @@ TEST_LIST = {
474646 { "encoding_gzip" , test_http_encoding_gzip },
475647 { "add_basic_auth_header" , test_http_add_basic_auth_header },
476648 { "add_proxy_auth_header" , test_http_add_proxy_auth_header },
649+ { "ipv6_host_header" , test_http_ipv6_host_header },
650+ { "ipv6_bracketed_host_header" , test_http_ipv6_bracketed_host_header },
651+ { "ipv4_host_header" , test_http_ipv4_host_header },
652+ { "domain_host_header" , test_http_domain_host_header },
653+ { "https_default_port_host_header" , test_https_default_port_host_header },
654+ { "ipv6_formats_host_header" , test_ipv6_formats_host_header },
655+ { "http_port_80_host_header" , test_http_port_80_host_header },
656+ { "port_443_without_tls_host_header" , test_port_443_without_tls_host_header },
657+ { "ipv6_zone_id_host_header" , test_ipv6_zone_id_host_header },
658+ { "https_non_standard_port_host_header" , test_https_non_standard_port_host_header },
659+ { "ipv6_bracketed_zone_id_host_header" , test_ipv6_bracketed_zone_id_host_header },
660+ { "https_ipv6_default_port_host_header" , test_https_ipv6_default_port_host_header },
661+ { "https_ipv6_non_standard_port_host_header" , test_https_ipv6_non_standard_port_host_header },
662+ { "https_ipv6_zone_id_default_port_host_header" , test_https_ipv6_zone_id_default_port_host_header },
663+ { "https_ipv6_zone_id_non_standard_port_host_header" , test_https_ipv6_zone_id_non_standard_port_host_header },
477664 { 0 }
478665};
0 commit comments