C++调用Telegram Bot API发送GET请求返回301 Moved Permanently问题求助
解决Telegram Bot API请求返回301 Moved Permanently的问题
我一看你遇到的这个问题就明白咋回事了——Telegram Bot API现在强制要求使用HTTPS协议访问,而你代码里用的是80端口的HTTP请求,这就导致服务器返回301永久重定向,把你导向HTTPS的地址。浏览器会自动帮你处理重跳转,但Boost Beast默认不会自动跟进,所以你就直接拿到了301响应。
问题根源
- Telegram Bot API早已不再支持纯HTTP(80端口)请求,所有请求必须走HTTPS(443端口)并通过SSL/TLS加密
- 你测试的其他站点(比如google.com、ip2c.org)仍支持HTTP访问,所以代码能正常工作
修改后的完整代码
下面是调整后的代码,核心是改用HTTPS连接,加入SSL加密层:
#include <boost/beast.hpp> #include <boost/beast/ssl.hpp> #include <boost/asio.hpp> #include <iostream> #include <string> namespace http = boost::beast::http; namespace net = boost::asio; namespace ssl = boost::asio::ssl; using tcp = boost::asio::ip::tcp; int main() { try { const std::string host = "api.telegram.org"; const std::string target = "/bot1781233486:AAENIwkZt0Lbv9zjks6l-4loBcWDzKyMhyU/sendMessage?chat_id=@ZiyodaEnglishPracticeTracker&text=Test+message+from+bot"; net::io_context ioc; ssl::context ctx(ssl::context::tlsv12_client); ctx.set_default_verify_paths(); tcp::resolver resolver(ioc); ssl::stream<tcp::socket> stream(ioc, ctx); // 验证服务器证书(可选但推荐) if(! SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) { throw boost::system::system_error( static_cast<int>(::ERR_get_error()), net::error::get_ssl_category()); } auto const results = resolver.resolve(host, "443"); net::connect(stream.next_layer(), results); stream.handshake(ssl::stream_base::client); http::request<http::string_body> req(http::verb::get, target, 11); req.set(http::field::host, host); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); http::write(stream, req); boost::beast::flat_buffer buffer; http::response<http::dynamic_body> res; http::read(stream, buffer, res); std::cout << res << std::endl; boost::beast::error_code ec; stream.shutdown(ec); if(ec == net::error::eof) { ec = {}; } if(ec) { throw boost::system::system_error(ec); } } catch(std::exception const& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } return 0; }
关键修改点说明
- 引入了
boost/beast/ssl.hpp和boost/asio/ssl.hpp来支持SSL加密 - 把连接端口从
"80"改成了HTTPS标准端口"443" - 使用
ssl::stream<tcp::socket>替代普通的tcp::socket,处理加密通信 - 添加了SSL握手步骤
stream.handshake(ssl::stream_base::client) - 增加了服务器证书验证的逻辑(这是生产环境中推荐的安全做法)
额外提示
如果你遇到证书验证失败的问题,可以暂时关闭验证(仅用于测试),但生产环境一定要开启:
// 仅测试用,生产环境不要这么做 ctx.set_verify_mode(ssl::verify_none);
另外,如果你想让代码自动处理重定向(比如遇到301/302时自动跳转),可以在收到响应后检查状态码,然后提取Location头字段重新发起请求,但直接改用HTTPS是更高效的解决方案。
内容的提问来源于stack exchange,提问作者Ulug'bek Abdimanabov
相关产品推荐
相关产品推荐

