【发布时间】:2016-06-15 16:14:23
【问题描述】:
再一次,我发现自己正在努力提升精神。我又一次发现自己被它打败了。
HTTP 头 value 采用一般形式:
text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1
即value *OWS [; *OWS name *OWS [= *OWS possibly_quoted_value] *OWS [...]] *OWS [ , <another value> ...]
所以在我看来,这个标头解码为:
value[0]:
text/html
params:
name : q
value : 1.0
value[1]:
text/*
params:
name : q
value : 0.8
...
等等。
我敢肯定,对于任何知道怎么做的人来说,boost::spirit::qi 的语法都是微不足道的。
我谦虚地请求您的帮助。
例如,这里是解码Content-Type 标头的代码大纲,该标头限制为type/subtype 形式的一个值,以及<sp> ; <sp> token=token|quoted_string 形式的任意数量的参数
template<class Iter>
void parse(ContentType& ct, Iter first, Iter last)
{
ct.mutable_type()->append(to_lower(consume_token(first, last)));
consume_lit(first, last, '/');
ct.mutable_subtype()->append(to_lower(consume_token(first, last)));
while (first != last) {
skipwhite(first, last);
if (consume_char_if(first, last, ';'))
{
auto p = ct.add_parameters();
skipwhite(first, last);
p->set_name(to_lower(consume_token(first, last)));
skipwhite(first, last);
if (consume_char_if(first, last, '='))
{
skipwhite(first, last);
p->set_value(consume_token_or_quoted(first, last));
}
else {
// no value on this parameter
}
}
else if (consume_char_if(first, last, ','))
{
// normally we should get the next value-token here but in the case of Content-Type
// we must barf
throw std::runtime_error("invalid use of ; in Content-Type");
}
}
}
ContentType& populate(ContentType& ct, const std::string& header_value)
{
parse(ct, header_value.begin(), header_value.end());
return ct;
}
【问题讨论】:
-
你能链接 RFC 吗?我不认识那个规范。
-
@sehe 非常感谢。我可能写得不太好...w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2
-
@sehe 在我看来,关于 HTTP 标头的有趣(实际上非常复杂)的事情是,'/' 是一个分隔符,它将值中的值分开。所以实际上 value[0] 本身应该是一个值向量:“text”、“html”以及添加的属性(“q”="1.0")等等。
-
@RichardHodges:在与
boost::asio相关联的示例代码中给出了一个非常简单的http 标头解析器:boost.org/doc/libs/1_61_0/doc/html/boost_asio/example/cpp11/… 但是,它的优点和精神的缺点就是那种如果解析器用完了要解析的文本,则解析器可以“中断”并恢复。 Spirit 不支持“三态”解析,即“好、失败、未完成”。在精神上 AFAIK 如果您用完了要解析的文本,解析器的状态将在返回时丢失。所以,我认为你实际上并不需要精神。 -
我猜你可能没有将它用于服务器或其他东西,或者你在某种情况下使用它,你将始终拥有完整的标头,或者可以负担得起重新解析?跨度>
标签: c++ boost boost-spirit boost-spirit-qi