Boost asio自定义HTTP服务器读取HTTP发布请求 [英] Boost asio custom HTTP server reading HTTP post requests

查看:788
本文介绍了Boost asio自定义HTTP服务器读取HTTP发布请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的C ++应用程序需要HTTP服务器,因此我决定自己制作一个,该服务器在发送HTTP Get请求时可以正常工作,但在读取HTTP Post请求时会遇到一些问题.

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.

问题在于,在发送HTTP Posts请求时,无法正确读取最后一个标头,因此我无法获取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.

这是我的代码:

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);
    });
}

buff_data_变量声明为:boost::asio::streambuf. HttpSession类是用于存储标头并处理所有网页服务的类.我没有包含该类的代码,因为这不是问题.

The buff_ and data_ variable are declared as: boost::asio::streambuf. And the HttpSession class is the one which stores the headers and handles all the webpage serving. I didn't include the code of that class since it's not the problem.

到/url的HTTP Post请求的输出是这样的:

The output of an HTTP Post request to /url is this one:

"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:"

因此,如您所见,尽管在该图中可以看到POST请求已正确发出,但是Accept-Language标头未正确读取.

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.

请注意,在发送GET请求时,一切正常.所以我的猜测是,它与异步读取有关,因为async_read_until不会阻塞,因此readBody函数的async_read会先读取.那我应该同步阅读吗?如果我为每个客户端创建一个HttpSession类,那么无论哪种方式都可以处理多个客户端? (我确实不需要支持一个以上的用户,但是,仍然很好).

Note that when sending GET requests everything works properly. 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. 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? (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!

推荐答案

我认为问题出在'\r\n\r\n'.那不是一个字符串,而是一个char.

I think the problem is with '\r\n\r\n'. That's not a string but a 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]

尝试将其替换为"\r\n\r\n".

这篇关于Boost asio自定义HTTP服务器读取HTTP发布请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆