Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

random port #126

Closed
qwertzui11 opened this issue Oct 13, 2020 · 7 comments
Closed

random port #126

qwertzui11 opened this issue Oct 13, 2020 · 7 comments

Comments

@qwertzui11
Copy link

hi. Thx for your great on this awesome framework.

I'd like to host the server on a random port. Aka using port 0 and then call some method like get_port(). asio::*::acceptor assigns on port 0 a random port.
This is useful when it comes to unittests, that may run in parallel.
I could not find any information on that topic. Is there a possibility to set the port to 0 and then retreive it?

so far I got:

using server_t = restinio::http_server_t<>;
using settings_t = restinio::server_settings_t<>;

server_t srv1{
    restinio::external_io_context(*context),
    settings_t{}.port(0).address("localhost").request_handler([](auto) {
      return restinio::request_accepted();
    })};
#if 0
srv1.get_port(); // does not work. desperate experiment ;-)
#endif

thx for ur time!

@eao197
Copy link
Member

eao197 commented Oct 13, 2020

Hi! Thanks for reporting this use-case.

We've never used RESTinio in such scenarios. I'll investigate the behavior of RESTinio's acceptor and reply to you back later.

@eao197
Copy link
Member

eao197 commented Oct 13, 2020

At this time I don't see an easy way to pass the actual local_endpoint of the acceptor to the outside of http_server_t instance. One of the reasons is the fact that that local_endpoint will be known only after completion of http_server_t::open_sync method, but this moment is hard to detect from the outside of http_server_t instance.

One of the current ideas is to add another callback to server_settings_t. Something like:

asio::ip::tcp::endpoint server_endpoint;
...
server_t srv1{
    restinio::external_io_context(*context),
    settings_t{}.port(0).address("localhost")
      .post_acceptor_bind_hook([&server_endpoint](asio::ip::tcp::acceptor & acceptor) {
            server_endpoint = acceptor.local_endpoint();
         })
      .request_handler([](auto) {
         return restinio::request_accepted();
      })};
...

But I'm not sure that's a good idea yet. Will think further.

@qwertzui11
Copy link
Author

I don't know this library well enough, nor its design.

hoooowever some ideas 😆

  • inject a factory for asio::ip::tcp::acceptor, and more? like for resolver and more.
  • open_sync could return a result that contains a port and maybe some other information thats available after the open. like the resolved bind endpoint?

eao197 added a commit that referenced this issue Oct 16, 2020
acceptor_post_bind_hook is introduced.
@eao197
Copy link
Member

eao197 commented Oct 19, 2020

Hi @qwertzui11 !

A new post-bind callback is added to RESTinio. You can see an example of its usage here:

std::promise<unsigned short> server_port_promise;
auto server_port_future = server_port_promise.get_future();
namespace asio_ns = restinio::asio_ns;
http_server_t http_server{
restinio::own_io_context(),
[&server_port_promise]( auto & settings ){
settings
.port( 0u )
.address( "127.0.0.1" )
.acceptor_post_bind_hook(
[&server_port_promise]( asio_ns::ip::tcp::acceptor & acceptor ) {
server_port_promise.set_value(
acceptor.local_endpoint().port() );
} )
.request_handler(
[]( auto req ){
req->create_response()
.append_header( "Server", "RESTinio utest server" )
.append_header_date_field()
.append_header( "Content-Type", "text/plain; charset=utf-8" )
.set_body(
restinio::const_buffer( req->header().method().c_str() ) )
.done();
return restinio::request_accepted();
} );
} };
other_work_thread_for_server_t<http_server_t> other_thread(http_server);
other_thread.run();
std::string response;
const char * request_str =
"GET / HTTP/1.1\r\n"
"Host: 127.0.0.1\r\n"
"User-Agent: unit-test\r\n"
"Accept: */*\r\n"
"Connection: close\r\n"
"\r\n";
REQUIRE_NOTHROW( response = do_request(
request_str, "127.0.0.1", server_port_future.get() ) );

The new functionality is in 0.6-dev-0.6.11 branch now. I plan to add yet more functionality into v.0.6.11 before the public release of that version. Hope I can complete it in a week, but it hard to predict. So if you can't wait please let us know.

@qwertzui11
Copy link
Author

excellent. I'll wait and try it out as soon as it's available on conan. Thx for the great work! 😍

@eao197
Copy link
Member

eao197 commented Oct 21, 2020

It seems that the scope of v.0.6.11 is completed. We have to update to docs and then the release will be published.

@qwertzui11
Copy link
Author

works! awesome, thx!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants