使用Boost.Beast调用Telegram Bot getUpdates接口返回400错误
解决Telegram Bot API POST请求400错误(Boost HTTP客户端)
我尝试通过POST请求调用Telegram Bot API的getUpdates接口,请求地址为POST https://api.telegram.org/bot<token>/getUpdates。这个请求在Postman中能正常执行,返回的响应如下:
{ "ok": true, "result": [ { "update_id": 22720266, "message": { "message_id": 25, "from": { "id": 67825600, "is_bot": false,... (etc) ... } ] }
但用C++ Boost HTTP客户端发送相同请求时,返回400 Bad Request错误:
HTTP/1.1 400 Bad Request Server: nginx/1.18.0 Date: Thu, 16 Jan 2025 12:52:52 GMT Content-Type: text/html Content-Length: 157 Connection: close <html> <head><title>400 Bad Request</title></head> <body> <center><h1>400 Bad Request</h1></center> <hr><center>nginx/1.18.0</center> </body> </html>
相关代码
我参考Boost官方异步/同步SSL客户端示例修改了代码,HTTP(非SSL)版本代码:
int main(int argc, char** argv){ //POST https://api.telegram.org/bot<..token..>/getUpdates auto const host = "https://api.telegram.org"; auto const port = "80"; auto const target = "/bot<..token..>/getUpdates"; int version = 11; // The io_context is required for all I/O net::io_context ioc; // Launch the asynchronous operation std::make_shared<session>(ioc)->run(host, port, target, version); // Run the I/O service. The call will return when // the get operation is complete. ioc.run(); return EXIT_SUCCESS; }
请求构建代码:
// Start the asynchronous operation void run(char const* host, char const* port, char const* target, int version) { // Set up an HTTP POST: req_.version(version); req_.method(http::verb::post); req_.target(target); req_.set(http::field::host, host); req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); req_.set(http::field::content_type, "application/json"); req_.content_length(0); // Look up the domain name resolver_.async_resolve( host, port, beast::bind_front_handler( &session::on_resolve, shared_from_this())); }
SSL版本仅将端口改为443,握手stream.handshake(ssl::stream_base::client);可正常完成,但仍返回相同400错误。请求日志显示Host字段包含完整URL。
解决建议
- 修正Host字段值:Host字段应该只填纯域名
api.telegram.org,不要带https://前缀。当前代码中host变量设置为带协议的完整URL,导致Host头不符合HTTP规范,这是400错误的核心原因。 - 匹配端口与协议:HTTP协议对应80端口,HTTPS必须使用443端口,确保SSL版本的端口设置正确。
- 优化请求头设置:
getUpdates接口的POST请求可以不带请求体,此时可以去掉Content-Type: application/json字段,避免不必要的头部信息干扰。 - 修正域名解析参数:resolver解析域名时,host参数必须是纯域名,不能带协议前缀,否则可能导致解析异常。
修改后的关键代码示例
// main函数中修正host和端口(SSL版本) auto const host = "api.telegram.org"; auto const port = "443"; auto const target = "/bot<..token..>/getUpdates"; int version = 11; // run函数中修正Host头 req_.set(http::field::host, host); // 此时host为纯域名 // 可选:移除无请求体时的Content-Type字段 // req_.set(http::field::content_type, "application/json");
内容的提问来源于stack exchange,提问作者Pavel Sh
相关产品推荐
相关产品推荐

