简体   繁体   English

Boost asio自定义HTTP服务器读取HTTP发布请求

[英]Boost asio custom HTTP server reading HTTP post requests

My C++ application requires of an HTTP server and I decided to make my own, which is correctly working when sending HTTP Get requests but has some problems when reading HTTP Post requests. 我的C ++应用程序需要HTTP服务器,因此我决定自己制造一个服务器,该服务器在发送HTTP Get请求时可以正常工作,但在读取HTTP Post请求时会遇到一些问题。

The problem is that when sending HTTP Posts requests, the last header isn't read properly, so I can't get the post request. 问题在于,在发送HTTP Posts请求时,无法正确读取最后一个标头,因此我无法获取post请求。

This is my code: 这是我的代码:

void HttpSession::readHeaders(std::shared_ptr<HttpSession> pThis) {
    boost::asio::async_read_until(pThis->socket_, pThis->buff_, '\r\n\r\n',
                              [pThis](const boost::system::error_code &e, std::size_t s) {
        std::istream headersStream(&pThis->buff_);
        std::string header;
        while(std::getline(headersStream, header, '\n')) {
            if(header != "\r") {
                if(header.back() == '\r') header = header.substr(0, header.length() - 1);
                qDebug() << QString::fromStdString(header);
                //Some stuff to get content-length to contentLength_
        }
    }

    if(contentLength_ > 0) {
        qDebug() << "Reading:";
        readBody(pThis);
    }

    std::shared_ptr<std::string> str = std::make_shared<std::string>(pThis->headers_.getResponse());
    boost::asio::async_write(pThis->socket_, boost::asio::buffer(str->c_str(), str->length()),
                             [pThis, str](const boost::system::error_code &e, std::size_t s) {
        qDebug() << "Written";
    });
}

void HttpSession::readBody(std::shared_ptr<HttpSession> pThis) {
    boost::asio::async_read(pThis->socket_, pThis->data_, boost::asio::transfer_at_least(1),
                              [pThis](const boost::system::error_code &e, std::size_t s) {
        std::istream body(&pThis->data_);
        std::string line;
        body >> line;
        qDebug() << QString::fromStdString(line);
    });
}

The buff_ and data_ variable are declared as: boost::asio::streambuf . buff_data_变量声明为: boost::asio::streambuf And the HttpSession class is the one which stores the headers and handles all the webpage serving. HttpSession类是一种用于存储标头并处理所有网页服务的类。 I didn't include the code of that class since it's not the problem. 我没有包含该类的代码,因为这不是问题。

The output of an HTTP Post request to /url is this one: 到/ url的HTTP Post请求的输出是这样的:

"POST /url HTTP/1.1" 
"Host: 192.168.1.41:8080" 
"Connection: keep-alive" 
"Content-Length: 10" 
"Cache-Control: max-age=0" 
"Origin: http://192.168.1.41:8080" 
"Upgrade-Insecure-Requests: 1" 
"User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36" 
"Content-Type: application/x-www-form-urlencoded" 
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" 
"Referer: http://192.168.1.41:8080/" 
"Accept-Encoding: gzip, deflate" 
"Accept-Langua" 
Reading:  
"ge:"

So as you can see, the Accept-Language header is not read properly although in this image you can see that the POST request is made properly. 因此,您可以看到,虽然在该图中可以看到POST请求是正确发出的,但是没有正确读取Accept-Language标头。 这个

Note that when sending GET requests everything works properly. 请注意,发送GET请求时,一切正常。 So my guess is that it has something to do with reading asynchronously, since the async_read_until doesn't block, so async_read of the readBody function, reads before it should. 所以我的猜测是,它是与阅读异步,因为async_read_until不会阻塞,所以async_read的的readBody功能,读取之前它应该。 Should I read synchronously, then? 那我应该同步阅读吗? Will I be able to handle more than one client either way if I create one HttpSession class for each client? 如果我为每个客户端创建一个HttpSession类,那么无论哪种方式都可以处理多个客户端? (I really don't need to support more than one user, but still, it would be nice). (我确实不需要支持一个以上的用户,但是仍然可以)。

For the client handling I do like this: 对于客户处理,我喜欢这样:

void HttpServer::run() {
    using namespace boost::asio;
    io_service io_service;
    ip::tcp::endpoint endpoint{ip::tcp::v4(), 8080};
    ip::tcp::acceptor acceptor{io_service, endpoint};
    acceptor.listen();
    runServer(acceptor, io_service);

    io_service.run();

    while(true) QThread::msleep(5000);
}

void HttpServer::runServer(boost::asio::ip::tcp::acceptor& acceptor, boost::asio::io_service& io_service) {
    std::shared_ptr<HttpSession> ses = std::make_shared<HttpSession>(io_service);
    acceptor.async_accept(ses->socket_,
    [ses, &acceptor, &io_service](const boost::system::error_code& accept_error) {
       runServer(acceptor, io_service);
       if(!accept_error) HttpSession::interact(ses);
    });
}

All kind of help will be appreciated! 各种帮助将不胜感激! If you have any code improvement, please tell me. 如果您对代码有任何改进,请告诉我。 Thanks! 谢谢!

I think the problem is with '\\r\\n\\r\\n' . 我认为问题出在'\\r\\n\\r\\n' That's not a string but a char . 那不是字符串,而是一个char

The compiler should normally warn you about this, with something like: 编译器通常应通过以下方式警告您:

warning: implicit conversion from 'int' to 'char' changes value from 218762506 to 10 [-Wconstant-conversion]

Try replacing that with "\\r\\n\\r\\n" . 尝试将其替换为"\\r\\n\\r\\n"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM