You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:17:02