1

I'm having trouble to get the protocol (HTTP or HTTPS) of a request in boost beast webserver.

I can get the host using:

req[http::field::host]

but no such luck with the protocol.

req[http::field::protocol]

is empty.

Drewes
  • 2,581
  • 1
  • 18
  • 18

2 Answers2

0

There is no http::field for HTTPS.

For using HTTPS basically you are doing following (example):

1.Create io_context and ssl_context

boost::asio::io_context ioc;
boost::asio::ssl::context ctx(boost::asio::ssl::context::tlsv12_client)

2.create ssl stream from io_context and ssl::context

boost::beast::ssl_stream<boost::beast::tcp_stream> stream(ioc, ctx)

3.create tcp connection using lowest_layer

beast::get_lowest_layer(stream).connect(...endpoints iterator from query resolver..)

4.do the ssl handshake

stream.handshake(ssl::stream_base::client);

5.now you can make requests writing to stream as usual:

 http::request<http::string_body> req{http::verb::get, target, version};
 req.set(http::field::host, host);
 req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);

// Send the HTTP request to the remote host
 http::write(stream, req);

Check the official boost beast examples.

StPiere
  • 4,113
  • 15
  • 24
  • 1
    I’m writing a server not a client. The server is http behind a nginx proxy. I need to find out it the client browser connects using https or http. Something like $server[SERVER_PROTOCOL] in PHP. – Drewes Sep 14 '20 at 16:33
  • YOU (server) decide which protocol you provide on each port. Normally 80=HTTP, 443=HTTPS. If the client connects on 443 in this example, that means HTTPS -> SSL handshake has to be maked. So I dont quite get your question, sorry. In the question you asked about makeing HTTP request -> it's the clientside, not server. – StPiere Sep 14 '20 at 18:06
  • Seems to be misunderstanding here. I'm pretty sure the question is not Beast related: we're talking about which headers we can use to figure out which protocol is being used. OP said it: he's behind a nginx proxy. It's very possible that connections to the Beast server are done with HTTP, _even_ when the client uses HTTPS. I think he doesn't care what protocol is used for the Beast connection: what he wants to know is the protocol being used by the connection between the client and nginx. There are headers for that, like HTTP_X_FORWARDED_SSL or HTTP_X_FORWARDED_PROTO. – Michael Dec 28 '22 at 01:45
0

Considering the fact that you are behind a nginx server, Beast cannot solve your problem. But the additional headers that nginx will send to your server will.

You may rely on the HTTP_X_FORWARDED_PROTO or HTTP_X_FORWARDED_SSL headers. Here's what I came up with by following an answer to a similar question:

using namespace boost::beast;
using namespace std;

string find_scheme(const http::request<http::string_body>& request)
{
  http::request<http::string_body>::const_iterator header;

  header = request.find("HTTP_X_FORWARDED_PROTO");                                                                    
  if (header != request.end())                                                                                        
    return header->value().data();                                                                                    
  else
  { 
    header = request.find("HTTP_X_FORWARDED_SSL");                                                                    
    if (header != request.end())
      return header->value() == "on" ? "https" : "http";                                                              
  }     
  return "http";
}
Michael
  • 1,357
  • 3
  • 15
  • 24