Error: Illegal or missing hexadecimal sequence in chunked-encoding
Error: Illegal or missing hexadecimal sequence in chunked-encoding
我正在编写自己的 http 服务器,现在我正在尝试实现分块传输编码。我的尝试是这样的:
void HttpServer::SendRespons(HttpServer::Connection &socket_) noexcept {
int sent = 0;
int counter = 0;
int index = 0;
std::size_t response_size_;
std::ifstream t(this->conf_.GetRootPath() + socket_.data);
socket_.respons = {(std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>()};
t.clear();
response_size_ = socket_.respons.size();
std::vector<std::string> strVec;
strVec.reserve(socket_.respons.size() / BUFSIZE + 2);
strVec.push_back(
"HTTP/1.1 200 OK\r\nServer: http\r\nContent-Type: "
"text/html\r\nTransfer-Encoding: "
"chunked\r\nConnection: Keep-Alive\r\n\r\n");
while (index + 16374 < static_cast<int>(response_size_)) {
strVec.push_back("3ff6\r\n" + socket_.respons.substr(index, 16374) +
"\r\n\r\n");
index += 16374;
}
std::stringstream stream;
stream << std::hex
<< std::atoi(std::to_string(response_size_ - index).c_str());
strVec.push_back(stream.str() + "\r\n" +
socket_.respons.substr(index, response_size_ - index) +
"\r\n\r\n");
strVec.push_back("0\r\n\r\n");
index = 0;
response_size_ += (strVec[0].size() + strVec[strVec.size() - 1].size());
std::lock_guard<std::mutex> lg(this->connected_clients_mux_);
while (index < static_cast<int>(strVec.size())) {
int len =
write(socket_.socket, (char *)&strVec[index][0], strVec[index].size());
if (len < 0) {
//...
} else if ((errno == EPIPE) || (errno == ECONNRESET)) {
std::cout << __FILE__ << " " << __func__
<< " sent stop (epipe || econreset), len= " << len << " "
<< "error #" << errno << std::endl;
break;
//...
}
++index;
sent += len;
std::cout << __FILE__ << " " << __func__ << " sent " << len << " "
<< "packet #" << ++counter << std::endl;
}
std::cout << std::endl
<< __FILE__ << " " << __func__
<< " assumed length:" << response_size_
<< " sent:" << sent << " to: " << socket_.socket << std::endl;
}
上面的函数应该读取文件,把它分成几部分,然后一个一个地传递。据我所知,拆分进行得很好,但是在尝试发送文件时:
curl -v http://localhost:8080/filename
我得到:
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /filename HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: http
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: Keep-Alive
<
//.... here is first chunk
* Illegal or missing hexadecimal sequence in chunked-encoding
* Closing connection 0
curl: (56) Illegal or missing hexadecimal sequence in chunked-encoding
如您所见,客户端收到响应的第一部分 (headers) 并对其进行处理。之后 - 它需要消息的 body。收到它的第一部分后,连接将关闭。我知道错误是以我自己的块的格式写在消息中的某处,但我自己无法弄清楚到底在哪里。我遵循了 https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Format 的指示,但 obv 犯了一个错误。
由于客户端没有输出它期望的十六进制序列的任何内容,因此它收到并认为错误的十六进制序列没有任何内容,我请求帮助。
我认为这部分代码的末尾只需要一个\r\n
。
strVec.push_back("3ff6\r\n" + socket_.respons.substr(index, 16374) +
"\r\n\r\n");
你不应该在前一个块和下一个块的十六进制大小之间插入一个空行。
(最后一块也是如此)
您提供的 wikipedia page 在示例中的块之间插入空行只是为了增加可读性,但实际上并没有发送这些空行。
我正在编写自己的 http 服务器,现在我正在尝试实现分块传输编码。我的尝试是这样的:
void HttpServer::SendRespons(HttpServer::Connection &socket_) noexcept {
int sent = 0;
int counter = 0;
int index = 0;
std::size_t response_size_;
std::ifstream t(this->conf_.GetRootPath() + socket_.data);
socket_.respons = {(std::istreambuf_iterator<char>(t)),
std::istreambuf_iterator<char>()};
t.clear();
response_size_ = socket_.respons.size();
std::vector<std::string> strVec;
strVec.reserve(socket_.respons.size() / BUFSIZE + 2);
strVec.push_back(
"HTTP/1.1 200 OK\r\nServer: http\r\nContent-Type: "
"text/html\r\nTransfer-Encoding: "
"chunked\r\nConnection: Keep-Alive\r\n\r\n");
while (index + 16374 < static_cast<int>(response_size_)) {
strVec.push_back("3ff6\r\n" + socket_.respons.substr(index, 16374) +
"\r\n\r\n");
index += 16374;
}
std::stringstream stream;
stream << std::hex
<< std::atoi(std::to_string(response_size_ - index).c_str());
strVec.push_back(stream.str() + "\r\n" +
socket_.respons.substr(index, response_size_ - index) +
"\r\n\r\n");
strVec.push_back("0\r\n\r\n");
index = 0;
response_size_ += (strVec[0].size() + strVec[strVec.size() - 1].size());
std::lock_guard<std::mutex> lg(this->connected_clients_mux_);
while (index < static_cast<int>(strVec.size())) {
int len =
write(socket_.socket, (char *)&strVec[index][0], strVec[index].size());
if (len < 0) {
//...
} else if ((errno == EPIPE) || (errno == ECONNRESET)) {
std::cout << __FILE__ << " " << __func__
<< " sent stop (epipe || econreset), len= " << len << " "
<< "error #" << errno << std::endl;
break;
//...
}
++index;
sent += len;
std::cout << __FILE__ << " " << __func__ << " sent " << len << " "
<< "packet #" << ++counter << std::endl;
}
std::cout << std::endl
<< __FILE__ << " " << __func__
<< " assumed length:" << response_size_
<< " sent:" << sent << " to: " << socket_.socket << std::endl;
}
上面的函数应该读取文件,把它分成几部分,然后一个一个地传递。据我所知,拆分进行得很好,但是在尝试发送文件时:
curl -v http://localhost:8080/filename
我得到:
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /filename HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: http
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: Keep-Alive
<
//.... here is first chunk
* Illegal or missing hexadecimal sequence in chunked-encoding
* Closing connection 0
curl: (56) Illegal or missing hexadecimal sequence in chunked-encoding
如您所见,客户端收到响应的第一部分 (headers) 并对其进行处理。之后 - 它需要消息的 body。收到它的第一部分后,连接将关闭。我知道错误是以我自己的块的格式写在消息中的某处,但我自己无法弄清楚到底在哪里。我遵循了 https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Format 的指示,但 obv 犯了一个错误。 由于客户端没有输出它期望的十六进制序列的任何内容,因此它收到并认为错误的十六进制序列没有任何内容,我请求帮助。
我认为这部分代码的末尾只需要一个\r\n
。
strVec.push_back("3ff6\r\n" + socket_.respons.substr(index, 16374) +
"\r\n\r\n");
你不应该在前一个块和下一个块的十六进制大小之间插入一个空行。 (最后一块也是如此)
您提供的 wikipedia page 在示例中的块之间插入空行只是为了增加可读性,但实际上并没有发送这些空行。