Почему этот сервер C ++ ASIO, BEAST переходит в плохое состояние при выполнении запроса HTTPS / SSL - PullRequest
2 голосов
/ 03 апреля 2019

Я хочу написать сервер, который отвечает на HTTP-запросы.Мне плевать на HTTPS.Если кто-то выполняет HTTPS-запрос, я хочу отклонить его и продолжить другие HTTP-запросы.Мой код выглядит следующим образом:

#include <boost/asio.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <thread>
#include <iostream>
using namespace std;

int main(){
    boost::asio::io_context ioc;
    boost::asio::ip::tcp::acceptor acceptor(ioc, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), 8000));
    boost::beast::flat_buffer request_buffer;
    for(;;){
        boost::asio::ip::tcp::socket socket(ioc);
        acceptor.accept(socket);

        boost::beast::http::request<boost::beast::http::string_body> request;
        try{
            boost::beast::http::read(socket, request_buffer, request);
            cout << "OK" << endl;

            boost::beast::http::response<boost::beast::http::string_body> response(boost::beast::http::status::ok, request.version());
            std::string body = "hello";
            response.content_length(body.size());
            response.body() = std::move(body);
            boost::beast::http::write(socket, response);

        }catch(...){
            cout << "BAD" << endl;
        }
        socket.close();
    }
}

Я запускаю код и выполняю следующие запросы с помощью Firefox:

  1. запрос http
  2. запрос https
  3. http-запрос

Я ожидаю следующий вывод сервера:

OK
BAD
OK

Тем не менее, я получаю:

OK
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD
BAD

Функция, которая выбрасывает это boost::beast::http::read.Однако я не понимаю, почему.Между вызовами я создаю новый объект сокета, и поэтому я понимаю, что результат второго запроса не должен влиять на третий.Однако, очевидно, мое понимание не правильно.Может кто-нибудь объяснить, где мое понимание того, как работает ASIO и / или BEAST, неверно.Спасибо:)

1 Ответ

1 голос
/ 03 апреля 2019

HTTPS - это HTTP через поток SSL. Поток SSL реализован через обычный сокет TCP. Beast добавляет «Read», потому что он не видит HTTP-запрос, он просто видит то, что выглядит как случайные двоичные данные. Он не знает (и не обнаруживает, что это поток SSL).

Причина, по которой вы видите так много «плохих» линий, заключается в том, что Firefox видит поток TLS, пытающийся подключиться, а затем терпящий неудачу. Это просто повторяет соединение потока SSL. Таким образом, вы в конечном итоге несколько линий подключения BAD.

Вот почему порт HTTP по умолчанию равен 80, а порт HTTPS по умолчанию - 443. Соединение клиента HTTPS с сервером HTTP никогда не будет работать и будет давать результаты, которые вы видите.

UPDATE: Причина, по которой вы попадаете в цикл BAD, заключается в том, что request_buffer не очищается от ошибок, поэтому он содержит первое SSL-соединение данных, к которому продолжают добавляться данные при каждом чтении данных из новых сокетов.

Самое простое решение - переместить определение request_buffer в то же место, что и объект запроса. Или вы можете потреблять необработанных данных, прежде чем вернуться к началу цикла.

...