C++:从Poco::Net::HTTPServerRequest 中获取Content

一、使用 Poco::Net::HTMLForm

使用 Poco::Net::HTMLForm 获取 数据的方式如下:

virtual void handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override
{
    Poco::Net::HTMLForm form(req, req.stream());
    for(const auto &it : form)
    {
        //遍历 form 数据
        std::cout << it.first << ":" << it.second << std::endl;
    }
}

Poco::Net::HTMLForm 对象初始化的时候,会首先读取 req.stream() 中的数据,然后对数据进行解析。

解析过程在文件 poco/Net/src/HTMLForm.cpp 中。

从文件中可以看到,HTMLForm 只支持两种格式的数据:

  • multipart/form-data
  • 非multipart/form-data
 44 const std::string HTMLForm::ENCODING_URL           = "application/x-www-form-urlencoded";
 45 const std::string HTMLForm::ENCODING_MULTIPART     = "multipart/form-data";
 46 const int         HTMLForm::UNKNOWN_CONTENT_LENGTH = -1;

当 Poco 检测到 Content-Type 是 multipart/form-data 的时候,就会执行 void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler) 方法,如果不是 multipart/form-data ,那么就执行 void HTMLForm::readUrl(std::istream& istr) 方法。

  • HTMLForm::readMultipart() 方法会把每一个 part 作为一个 name:value 进行解析;如果遇到文件 ,就直接忽略这个文件的内容。
  • HTMLForm::readUrl()方法会把 content 内的所有内容作为很多 name:value 进行解析,'='作为name 和 value 的分隔符,'&'作为多个 name:value 之间的分隔符。获取name 和 value 后再进行 urldecode 解码。

Poco::Net::HTMLForm 的缺点就是把内容强制作为 form 进行解析,因为它根本不检查 Content-Type 是什么。

二、直接读取 req.stream()

如果接收到的数据是 json,那么最好不要使用 Poco::Net::HTMLForm,尤其是数据中有 '=' 存在的时候,Poco::Net::HTMLForm 会直接把 '=' 作为分隔符使用,'='左边的是 name,'='右边的是 value。

那么如何读取 json 数据呢?直接读取 req.stream(),然后再解析json数据,就像下面这样:

virtual void handleRequest(Poco::Net::HTTPServerRequest &req, Poco::Net::HTTPServerResponse &resp) override
{
    std::string data(std::istreambuf_iterator<char>(req.stream()), {});
    std::cout << data << std::endl;
}

读取出来的数据存储在了 data 变量中,可以使用 Poco::JSON::Parser 进行解析:

Poco::JSON::Parser jsonParser;
object = jsonParser.parse(data).extract<Poco::JSON::Object::Ptr>();
value = object->get("name").toString();
std::cout << value << std::endl;

C++:从Poco::Net::HTTPServerRequest 中获取Content

上一篇:Filter过滤器


下一篇:servlet开发步骤