使用Boost Asio进行带有大请求体的POST请求

3
我正在尝试使用boost :: asio向localhost:55001 / predict发出同步http POST请求,并发送一个大的请求体(约8784000个字符)。我可以使用Python中的“requests”包轻松完成此操作。我的服务器可以很好地处理大量数据,所以我知道问题可能不在服务器端。
问题: 我根据其他stack overflow帖子为boost :: asio POST请求设置了请求。以下是我设置POST请求的主要代码块。编辑:我需要使用Boost,因为我的客户端无法使用C ++ 11。
“features”变量包含一个非常长的字符串(360个表示为字符串的JSON由“&”分隔)。
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "POST " << /predict << " HTTP/1.1\r\n";
request_stream << "Host: " << localhost:55001 << "\r\n";
request_stream << "Content-Type: text/plain; charset=utf-8 \r\n";
request_stream << "Content-Length: " << features.length() << "\r\n";
request_stream << "Connection: close\r\n\r\n";
request_stream << features;

// Send the request
boost::asio::write(socket, request);

// Get the response
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");

我从服务器收到以下错误/响应:
Response returned with status code 413 libc++abi.dylib: terminating with uncaught exception of type boost::exception_detail::clone_impl >: (1): expected value 我向Jetty服务器发送请求时,它会抱怨HttpParser:HttpParser Full,这意味着请求过大。考虑到我能够使用Python的请求包发送完整请求,我知道Jetty服务器肯定能够处理此类大小的请求。然而,这意味着我在使用boost :: asio打包请求时出现了问题。
features仅包含2个JSON(仍由&分隔)时,一切都正常工作,并且响应包含我期望的结果。
我怀疑这个问题是因为我向缓冲区写入了太多数据,需要在单个请求中发送多个缓冲区。此外,我想象Python的请求包正在内部处理这些问题,这就是为什么Python代码运行良好的原因。这是我在Python中发送请求的代码行。
response = requests.post('http://localhost:55001/predict', data=features.encode('utf-8'))

1) 有人能解释一下如何使用boost::asio在同步POST请求的请求体中发送大量数据吗?我对C++不熟悉,所以示例会很有帮助。

2) Python的Request包是否将这些问题抽象化了?

如果需要提供其他信息来帮助您回答问题,请告诉我。谢谢!


request_stream << "POST " << /predict << " HTTP/1.1\r\n"; you need to change this to something like request_stream << "POST /predict/ HTTP/1.1 \r\n"; - Justin Randall
1个回答

0

Boost很棒,但如果你只是想使用HTTP GET和POST方法(并且你正在使用C++11),那么考虑使用cpr C++ Requests之类的东西。它是一个轻量级库,包装了libcurl,并模仿了Python Requests项目。

文档中,这里有一个快速制作POST请求的示例:

#include <cpr/cpr.h>

auto r = cpr::Post(cpr::Url{"http://www.httpbin.org/post"},
                   cpr::Body{"This is raw POST data"},
                   cpr::Header{{"Content-Type", "text/plain"}});
std::cout << r.text << std::endl;

/*
 * {
 *   "args": {},
 *   "data": "This is raw POST data",
 *   "files": {},
 *   "form": {},
 *   "headers": {
 *     ..
 *     "Content-Type": "text/plain",
 *     ..
 *   },
 *   "json": null,
 *   "url": "http://www.httpbin.org/post"
 * }
 */

感谢您的快速回复。我要在原帖中添加一个注意事项,即我不能使用C++11。我的客户仍然没有更新到这个版本,这就是为什么我正在尝试使用Boost的原因。如果有一种方法可以不依赖于C++11来完成cpr,那就太完美了。 - Aakash282
如果您无法使用C++11,则应尝试使用本机libcurl API,或者使用称为curlpp的C++包装器。 libcurl将完成您想要的所有操作,但您需要自己完成更多的重活。 - Justin Randall
好的,谢谢 - 我会尝试的。你知道libcurl是一个仅包含头文件的库吗?看起来我只需要包含<curl/curl.h>。 - Aakash282
@Aakash282 不,你必须链接到它。 - Justin Randall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接