Skip to content

Instantly share code, notes, and snippets.

@eao197
Created November 28, 2023 10:52
Show Gist options
  • Select an option

  • Save eao197/00272a76b3a358a580af2627c2d7fd88 to your computer and use it in GitHub Desktop.

Select an option

Save eao197/00272a76b3a358a580af2627c2d7fd88 to your computer and use it in GitHub Desktop.
Пример парсинга адреса сервера вида "http://localhost:8088/" имеющимися в RESTinio средствами. С разбором на составляющие: (http|https), (host|ipv6|ipv4) и опциональный порт
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>
#include <restinio/helpers/http_field_parsers/host.hpp>
namespace example
{
namespace ep = restinio::easy_parser;
using restinio::http_field_parsers::host_details::ipv4_address_p;
using restinio::http_field_parsers::host_details::ipv6_address_p;
using restinio::http_field_parsers::host_details::reg_name_p;
enum class protocol_t { http, https };
struct server_address_params_t
{
protocol_t m_protocol{ protocol_t::http };
std::string m_address{ "localhost" };
std::optional< std::uint16_t > m_port;
};
[[nodiscard]]
auto
server_address_params_p()
{
return ep::produce< server_address_params_t >(
ep::produce< protocol_t >(
ep::alternatives(
ep::exact_p( "https" )
>> ep::just( protocol_t::https ) >> ep::as_result(),
ep::exact_p( "http" )
>> ep::just( protocol_t::http ) >> ep::as_result()
)
) >> &server_address_params_t::m_protocol,
ep::exact( "://" ),
ep::produce< std::string >(
ep::alternatives(
ep::sequence(
ep::symbol( '[' ),
ipv6_address_p() >> ep::as_result(),
ep::symbol( ']' )
),
ipv4_address_p() >> ep::as_result(),
reg_name_p() >> ep::as_result()
)
) >> &server_address_params_t::m_address,
ep::produce< std::optional< std::uint16_t > >(
ep::maybe(
ep::symbol(':'),
ep::non_negative_decimal_number_p< std::uint16_t >() >> ep::as_result()
)
) >> &server_address_params_t::m_port,
ep::maybe( ep::symbol( '/' ) )
);
}
[[nodiscard]]
restinio::expected_t< server_address_params_t, ep::parse_error_t >
try_parse( std::string_view what )
{
return ep::try_parse( what, server_address_params_p() );
}
} /* namespace example */
TEST_CASE( "hostname" )
{
{
const auto r = example::try_parse( "http://localhost" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "localhost" == srv.m_address );
REQUIRE( !srv.m_port );
}
{
const auto r = example::try_parse( "http://localhost/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "localhost" == srv.m_address );
REQUIRE( !srv.m_port );
}
{
const auto r = example::try_parse( "http://localhost:8080" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "localhost" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 8080 == srv.m_port.value() );
}
{
const auto r = example::try_parse( "http://localhost:8080/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "localhost" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 8080 == srv.m_port.value() );
}
{
const auto r = example::try_parse( "http://my.host-name.com:55777/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "my.host-name.com" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 55777 == srv.m_port.value() );
}
{
const auto r = example::try_parse( "https://my.host-name.com:55777/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::https == srv.m_protocol );
REQUIRE( "my.host-name.com" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 55777 == srv.m_port.value() );
}
}
TEST_CASE( "ipv6" )
{
{
const auto r = example::try_parse( "http://[::]" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "::" == srv.m_address );
REQUIRE( !srv.m_port );
}
{
const auto r = example::try_parse( "http://[::]/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "::" == srv.m_address );
REQUIRE( !srv.m_port );
}
{
const auto r = example::try_parse( "http://[::1]/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "::1" == srv.m_address );
REQUIRE( !srv.m_port );
}
{
const auto r = example::try_parse( "http://[::]:8080" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "::" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 8080 == srv.m_port.value() );
}
{
const auto r = example::try_parse( "http://[::]:8080/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "::" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 8080 == srv.m_port.value() );
}
{
const auto r = example::try_parse( "http://[FF01::43]:55777/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "FF01::43" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 55777 == srv.m_port.value() );
}
{
const auto r = example::try_parse( "http://[::FFFF:129.144.52.38]:55777/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "::FFFF:129.144.52.38" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 55777 == srv.m_port.value() );
}
}
TEST_CASE( "ipv4" )
{
{
const auto r = example::try_parse( "http://127.0.0.1" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "127.0.0.1" == srv.m_address );
REQUIRE( !srv.m_port );
}
{
const auto r = example::try_parse( "http://127.0.0.1/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "127.0.0.1" == srv.m_address );
REQUIRE( !srv.m_port );
}
{
const auto r = example::try_parse( "http://127.0.0.1:8080" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "127.0.0.1" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 8080 == srv.m_port.value() );
}
{
const auto r = example::try_parse( "http://127.0.0.1:8080/" );
REQUIRE( true == r.has_value() );
const auto & srv = *r;
REQUIRE( example::protocol_t::http == srv.m_protocol );
REQUIRE( "127.0.0.1" == srv.m_address );
REQUIRE( true == srv.m_port.has_value() );
REQUIRE( 8080 == srv.m_port.value() );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment