我收到了一项作业,其中涉及使用 C++ 和 Boost Asio 库编写 Web 服务器。
我已经组装了一个工作服务器,它可以使用一本名为“Boost.Asio C++ Network Programming Cookbook”的书将 html 文件发送回客户端浏览器,但我正在努力处理来自客户端的 POST 请求。
当客户端连接到服务器时,他们会获得简单的 HTML 表单,其中包含用于登录服务器的用户名和密码字段,然后使用 POST 请求将其发送到服务器。
我已经将收到的POST请求的内容输出到控制台,我可以看到所有的 header 信息,但看不到表单数据。我已使用 Wireshark 检查数据包,并且数据正在通过网络发送。
服务器以 Boost Asio Streambuf 的形式接收数据,我通过将其读入 vector 然后获取相关元素(例如方法或目标)来解析它以获取请求的 HTML 文件。
有人对在哪里寻找有关如何解析表单数据的教程有任何建议吗?
下面的代码是 cpp 文件的一部分,它解析 POST 请求并根据请求的内容处理响应。 '&request' 参数是 Boost Asio Streambuf
我在网络编程方面经验很少,如果有任何建议,我将不胜感激!
解析请求的代码
// Prepare and return the response message.
// Parse the request from the client to find requested document
std::istream buffer(&request);
std::vector<std::string> parsed((std::istream_iterator<std::string>(buffer)), std::istream_iterator<std::string>() );
处理 POST 请求
else if (parsed.size() >= 3 && parsed[0] == "POST") {
htmlFile = "/files.html";
// Retrieve files from server file system. The second element in 'parsed' vector is file name
std::ifstream fileStream(".\\directory" + htmlFile);
// If the file exists then iterate it and assign the value to the content string variable, else return 404.
if (fileStream.good()) {
std::string fileContents((std::istreambuf_iterator<char>(fileStream)), std::istreambuf_iterator<char>());
content = fileContents;
code = "200 ok";
}
else {
std::ifstream fileStream(".\\directory\\404.html");
std::string fileContents((std::istreambuf_iterator<char>(fileStream)), std::istreambuf_iterator<char>());
content = fileContents;
code = "404";
}// End of nested if-else statement
}// End of else-if statement
else {
std::ifstream fileStream(".\\directory\\401.html");
std::string fileContents((std::istreambuf_iterator<char>(fileStream)), std::istreambuf_iterator<char>());
content = fileContents;
code = "401";
// Write bad request to log file for security audits if not "GET" request
logging.logAction("Illegal request by client IP " + m_sock->remote_endpoint().address().to_string());
}//End of if-else statement
std::ostringstream oss;
oss << "GET HTTP/1.1 " << code << " \r\n";
oss << "Cache-Control: no-cache, private" << "\r\n";
oss << "Content-Type: text/html" << "\r\n";
oss << "Content-Length: " << content.size() << "\r\n";
oss << "\r\n\r\n";
oss << content;
response = oss.str().c_str();
最佳答案
HTTP 是一种逐行协议(protocol)。 sample :https://www.tutorialspoint.com/http/http_requests.htm
POST /cgi-bin/process.cgi HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Content-Type: application/x-www-form-urlencoded
Content-Length: length
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
licenseID=string&content=string&/paramsXML=string
您需要进行更具体的解析,而不是将每个空格分隔的“单词”放入 vector 中。
从这样的事情开始:
#include <iostream>
#include <iomanip>
#include <boost/asio.hpp>
int main() {
boost::asio::streambuf request;
{
std::ostream sample(&request);
sample <<
"POST /cgi-bin/process.cgi HTTP/1.1\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)\r\n"
"Host: www.tutorialspoint.com\r\n"
"Content-Type: application/x-www-form-urlencoded\r\n"
"Content-Length: 49\r\n"
"Accept-Language: en-us\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Connection: Keep-Alive\r\n"
"\r\n"
"licenseID=string&content=string&/paramsXML=string"
;
}
std::istream buffer(&request);
std::string line;
// parsing the headers
while (getline(buffer, line, '\n')) {
if (line.empty() || line == "\r") {
break; // end of headers reached
}
if (line.back() == '\r') {
line.resize(line.size()-1);
}
// simply ignoring headers for now
std::cout << "Ignore header: " << std::quoted(line) << "\n";
}
std::string const body(std::istreambuf_iterator<char>{buffer}, {});
std::cout << "Parsed content: " << std::quoted(body) << "\n";
}
打印
Ignore header: "POST /cgi-bin/process.cgi HTTP/1.1"
Ignore header: "User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)"
Ignore header: "Host: www.tutorialspoint.com"
Ignore header: "Content-Type: application/x-www-form-urlencoded"
Ignore header: "Content-Length: 49"
Ignore header: "Accept-Language: en-us"
Ignore header: "Accept-Encoding: gzip, deflate"
Ignore header: "Connection: Keep-Alive"
Parsed content: "licenseID=string&content=string&/paramsXML=string"
关于c++ - 如何使用 C++ 和 Boost Asio 从 HTTP post 请求获取键值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59659968/