boost c++ 上的 vk api 无法正常工作
vk api on boost c++ doesn't work correctly
我写了一些应该发送 GET 请求并获得响应的代码。
它适用于 ip-api.com 和 returns 我 json 文件。
但是对于 api.vk.com 它 returns html 是这样的:
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>kittenx</center>
</body>
</html>
最有趣的是程序returns正确link,打开后会执行所需的GET请求。
main.cpp:
#include <iostream>
#include "client.hpp"
#include "json.hpp"
std::string get_token(const std::string &);
int main()
{
std::string token = get_token("data/token1");
std::string query = "https://api.vk.com/method/groups.getMembers?access_token=" + token + "&v=5.13&group_id=klubauto";
std::cout << query << "\n\n\n";
Client client(url);
client.send_request(query);
std::string response = client.get_response();
std::cout << response << std::endl;
return 0;
}
client.hpp:
#pragma once
#include <string>
#include <boost/beast.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
namespace http = boost::beast::http;
class Client
{
public:
Client();
Client(const std::string &api);
~Client();
void send_request(const std::string &arguments);
std::string get_response();
private:
boost::asio::io_context io;
boost::asio::ip::tcp::resolver resolver;
boost::asio::ip::tcp::socket socket;
std::string url;
};
client.cpp
#include "client.hpp"
/*
* Constructors
*/
Client::Client() : url("google.com"), resolver(io), socket(io)
{
boost::asio::connect(socket, resolver.resolve(url, "80"));
}
Client::Client(const std::string &api) : url(api), resolver(io), socket(io)
{
boost::asio::connect(socket, resolver.resolve(url, "80"));
}
/*
* Destructor
*/
Client::~Client()
{
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
}
/*
* Send request
*/
void Client::send_request(const std::string &arguments)
{
http::request<http::string_body> req(http::verb::get, arguments, 11);
req.set(http::field::host, url);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
http::write(socket, req);
}
/*
* Get response
*/
std::string Client::get_response()
{
std::string response;
{
boost::beast::flat_buffer buffer;
http::response<http::dynamic_body> res;
http::read(socket, buffer, res);
response = boost::beast::buffers_to_string(res.body().data());
}
return response;
}
我想在响应变量中接收一个 json 文件,请告诉我如何实现?
就像我评论的那样,这就是 HTTP 的工作原理:服务器可以重定向到 better/new 位置。
我认为这样做的主要原因是您的连接不是 HTTPS,而这正是 end-points 所要求的。所以,先解决这个问题。
接下来,您的查询包含基数 URL,这是另一个错误。
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <string>
namespace http = boost::beast::http;
namespace ssl = boost::asio::ssl;
using boost::asio::ip::tcp;
class Client {
public:
Client(const std::string& host = "google.com") : _host(host) {
_ctx.set_default_verify_paths();
connect(_socket.lowest_layer(),
tcp::resolver{_io}.resolve(_host, "https"));
_socket.handshake(ssl::stream_base::client);
}
void send_request(const std::string& query)
{
http::request<http::string_body> req(http::verb::get, query, 11);
req.set(http::field::host, _host);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
http::write(_socket, req);
}
std::string get_response() {
http::response<http::string_body> res;
boost::beast::flat_buffer buffer;
http::read(_socket, buffer, res);
return std::move(res.body());
}
private:
boost::asio::io_context _io;
ssl::context _ctx{ssl::context::sslv23_client};
ssl::stream<tcp::socket> _socket{_io, _ctx};
std::string _host;
};
#include <iostream>
#include <boost/json.hpp>
#include <boost/json/src.hpp> // for COLIRU header-only
namespace json = boost::json;
std::string get_token(const std::string&) { return ""; }
int main()
{
Client client("api.vk.com");
client.send_request("/method/groups.getMembers?access_token=" +
get_token("data/token1") + "&v=5.13&group_id=klubauto");
std::cout << json::parse(client.get_response()) << std::endl;
}
Coliru 不允许 public 网络访问:
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
what(): resolve: Service not found
但在我的机器上正确显示:
{"error":{"error_code":5,"error_msg":"User authorization failed: no access_token passed.","request_params":[{"key":"v","value":"5.13"},{"key":"group_id","value":"klubauto"},{"key":"method","value":"groups.getMembers"},{"key":"oauth","value":"1"}]}}
Note I included quite a number of simplifications along the way.
我写了一些应该发送 GET 请求并获得响应的代码。
它适用于 ip-api.com 和 returns 我 json 文件。
但是对于 api.vk.com 它 returns html 是这样的:
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>kittenx</center>
</body>
</html>
最有趣的是程序returns正确link,打开后会执行所需的GET请求。
main.cpp:
#include <iostream>
#include "client.hpp"
#include "json.hpp"
std::string get_token(const std::string &);
int main()
{
std::string token = get_token("data/token1");
std::string query = "https://api.vk.com/method/groups.getMembers?access_token=" + token + "&v=5.13&group_id=klubauto";
std::cout << query << "\n\n\n";
Client client(url);
client.send_request(query);
std::string response = client.get_response();
std::cout << response << std::endl;
return 0;
}
client.hpp:
#pragma once
#include <string>
#include <boost/beast.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
namespace http = boost::beast::http;
class Client
{
public:
Client();
Client(const std::string &api);
~Client();
void send_request(const std::string &arguments);
std::string get_response();
private:
boost::asio::io_context io;
boost::asio::ip::tcp::resolver resolver;
boost::asio::ip::tcp::socket socket;
std::string url;
};
client.cpp
#include "client.hpp"
/*
* Constructors
*/
Client::Client() : url("google.com"), resolver(io), socket(io)
{
boost::asio::connect(socket, resolver.resolve(url, "80"));
}
Client::Client(const std::string &api) : url(api), resolver(io), socket(io)
{
boost::asio::connect(socket, resolver.resolve(url, "80"));
}
/*
* Destructor
*/
Client::~Client()
{
socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both);
}
/*
* Send request
*/
void Client::send_request(const std::string &arguments)
{
http::request<http::string_body> req(http::verb::get, arguments, 11);
req.set(http::field::host, url);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
http::write(socket, req);
}
/*
* Get response
*/
std::string Client::get_response()
{
std::string response;
{
boost::beast::flat_buffer buffer;
http::response<http::dynamic_body> res;
http::read(socket, buffer, res);
response = boost::beast::buffers_to_string(res.body().data());
}
return response;
}
我想在响应变量中接收一个 json 文件,请告诉我如何实现?
就像我评论的那样,这就是 HTTP 的工作原理:服务器可以重定向到 better/new 位置。
我认为这样做的主要原因是您的连接不是 HTTPS,而这正是 end-points 所要求的。所以,先解决这个问题。
接下来,您的查询包含基数 URL,这是另一个错误。
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <string>
namespace http = boost::beast::http;
namespace ssl = boost::asio::ssl;
using boost::asio::ip::tcp;
class Client {
public:
Client(const std::string& host = "google.com") : _host(host) {
_ctx.set_default_verify_paths();
connect(_socket.lowest_layer(),
tcp::resolver{_io}.resolve(_host, "https"));
_socket.handshake(ssl::stream_base::client);
}
void send_request(const std::string& query)
{
http::request<http::string_body> req(http::verb::get, query, 11);
req.set(http::field::host, _host);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
http::write(_socket, req);
}
std::string get_response() {
http::response<http::string_body> res;
boost::beast::flat_buffer buffer;
http::read(_socket, buffer, res);
return std::move(res.body());
}
private:
boost::asio::io_context _io;
ssl::context _ctx{ssl::context::sslv23_client};
ssl::stream<tcp::socket> _socket{_io, _ctx};
std::string _host;
};
#include <iostream>
#include <boost/json.hpp>
#include <boost/json/src.hpp> // for COLIRU header-only
namespace json = boost::json;
std::string get_token(const std::string&) { return ""; }
int main()
{
Client client("api.vk.com");
client.send_request("/method/groups.getMembers?access_token=" +
get_token("data/token1") + "&v=5.13&group_id=klubauto");
std::cout << json::parse(client.get_response()) << std::endl;
}
Coliru 不允许 public 网络访问:
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
what(): resolve: Service not found
但在我的机器上正确显示:
{"error":{"error_code":5,"error_msg":"User authorization failed: no access_token passed.","request_params":[{"key":"v","value":"5.13"},{"key":"group_id","value":"klubauto"},{"key":"method","value":"groups.getMembers"},{"key":"oauth","value":"1"}]}}
Note I included quite a number of simplifications along the way.