eidheim / Simple-Web-Server

A very simple, fast, multithreaded, platform independent HTTP and HTTPS server and client library implemented using C++11 and Boost.Asio. Created to be an easy way to make REST resources available from C++ applications.
MIT License
2.61k stars 751 forks source link

How do you get the port number and detect when a connection has closed? #212

Open LB-- opened 6 years ago

LB-- commented 6 years ago

I'm implementing a native desktop app that has the user sign in with OAuth. In order for this to be possible, the app has to launch a local webserver on a random available port and use 127.0.0.1:port as the return address so that the app can receive the authentication information (or cancellation). Then when the user is directed to the local webserver, they should see a message telling them to return to the app, and the webserver should shutdown.

I am running into problems with this every step of the way. Firstly, the port number - using port 0 lets the operating system choose a random available port, and then the port can be queried with acceptor->local_endpoint().port(). However, since the acceptor is only initialized in start() and start() is called in a separate thread, there's no way to reliably know when it can be accessed. My current workaround is to just wait 100 milliseconds after starting the server and just hope that that is enough time, which is an obviously horrible hack.

Secondly, there's no way to know when the response has finished being sent. Since the user handler functions must return before the response can be sent, my app has no way of knowing when it is safe to shut down the server. I have tried counting the number of open connections but there is for some reason always one open connection at all times despite setting close_connection_after_response, I don't know what this is from. As a workaround I could include an image in the response body and shut down the server when that image is requested, but that's another obviously horrible hack on a number of levels.

Do you have any suggestions for how to deal with these problems?

eidheim commented 6 years ago

Thank you for reporting these issue. Especially the case when the server is using port 0 has to be fixed.

Regarding your second issue, here is a sample showing how to know if a response has finished or not:

#include "server_http.hpp"

using namespace std;
using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;

int main() {
  HttpServer server;
  server.config.port = 8080;

  server.default_resource["GET"] = [](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
    response->write("Hello");
    response->send([](const SimpleWeb::error_code &ec) {
      // response has been sent or errored
    });
  };

  server.start();
}
LB-- commented 6 years ago

here is a sample showing how to know if a response has finished or not:

Thank you, I'm a bit embarrassed I didn't find that myself. I can confirm that works exactly as needed.