Enable access to HTTP headers
This commit is contained in:
parent
233cb04268
commit
f9b6009b57
@ -1,6 +1,6 @@
|
||||
cmake_minimum_required (VERSION 3.7)
|
||||
project (mastodon-cpp
|
||||
VERSION 0.3.2
|
||||
VERSION 0.3.3
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
|
@ -108,7 +108,7 @@ If you use a debug build, you get more verbose error messages.
|
||||
* [x] Handle HTTP statuses 301, 302, 307 and 308
|
||||
* [x] Support registering as an application
|
||||
* Version 0.4.0
|
||||
* [ ] Handle X-RateLimit header
|
||||
* [x] Handle X-RateLimit header
|
||||
* [ ] Streaming API
|
||||
* Later
|
||||
* [ ] Asynchronous I/O
|
||||
|
53
src/examples/example8_rate_limiting.cpp
Normal file
53
src/examples/example8_rate_limiting.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/* This file is part of mastodon-cpp.
|
||||
* In this example we look at HTTP headers to determine how many calls we are
|
||||
* allowed to make.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include "../mastodon-cpp.hpp"
|
||||
|
||||
using Mastodon::API;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
std::cerr << "usage: " << argv[0] << " <instance> <access token>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
Mastodon::API masto(argv[1], argv[2]);
|
||||
masto.set_useragent("mastodon-cpp-example/1.3.3.7");
|
||||
std::string answer;
|
||||
std::uint16_t ret;
|
||||
|
||||
ret = masto.get(API::v1::accounts_verify_credentials, answer);
|
||||
if (ret == 0)
|
||||
{
|
||||
std::string remaining = masto.get_header("X-RateLimit-Remaining");
|
||||
std::string reset = masto.get_header("X-RateLimit-Reset");
|
||||
std::cout << "You are allowed to make " << remaining
|
||||
<< " calls until the counter is reset at " << reset << '\n';
|
||||
|
||||
if (std::stoi(remaining) <= 1)
|
||||
{
|
||||
std::cout << "🔥 Please let the server cool off a bit! 🔥\n";
|
||||
}
|
||||
}
|
||||
else if (ret == 3)
|
||||
{
|
||||
std::cerr << "The URL has permanently changed.\n" <<
|
||||
"New URL: " << answer << '\n';
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error code: " << ret << '\n';
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -65,6 +65,8 @@ const std::uint16_t API::http::request_sync(const method &meth,
|
||||
"Connection: close",
|
||||
"Authorization: Bearer " + _access_token
|
||||
});
|
||||
// Get headers from server
|
||||
request.setOpt<curlpp::options::Header>(true);
|
||||
request.setOpt<curlopts::FollowLocation>(true);
|
||||
request.setOpt<curlopts::WriteStream>(&oss);
|
||||
if (!formdata.empty())
|
||||
@ -93,9 +95,13 @@ const std::uint16_t API::http::request_sync(const method &meth,
|
||||
request.perform();
|
||||
std::uint16_t ret = curlpp::infos::ResponseCode::get(request);
|
||||
ttdebug << "Response code: " << ret << '\n';
|
||||
size_t pos = oss.str().find("\r\n\r\n");
|
||||
_headers = oss.str().substr(0, pos);
|
||||
|
||||
if (ret == 200 || ret == 302 || ret == 307)
|
||||
{ // OK or Found or Temporary Redirect
|
||||
answer = oss.str();
|
||||
// Only return body
|
||||
answer = oss.str().substr(pos + 4);
|
||||
}
|
||||
else if (ret == 301 || ret == 308)
|
||||
{ // Moved Permanently or Permanent Redirect
|
||||
@ -122,3 +128,8 @@ const std::uint16_t API::http::request_sync(const method &meth,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const void API::http::get_headers(string &headers) const
|
||||
{
|
||||
headers = _headers;
|
||||
}
|
||||
|
@ -216,3 +216,18 @@ const std::uint16_t API::register_app2(const string &instance,
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
const string API::get_header(const std::string &header) const
|
||||
{
|
||||
string headers;
|
||||
_http.get_headers(headers);
|
||||
size_t startpos = headers.find(header);
|
||||
if (startpos != std::string::npos)
|
||||
{
|
||||
startpos = headers.find(':', startpos) + 2;
|
||||
size_t endpos = headers.find("\r\n", startpos);
|
||||
return headers.substr(startpos, endpos - startpos);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
* @example example5_follow_unfollow.cpp
|
||||
* @example example6_toot_delete-toot.cpp
|
||||
* @example example7_register_app.cpp
|
||||
* @example example8_rate_limiting.cpp
|
||||
*/
|
||||
namespace Mastodon
|
||||
{
|
||||
@ -472,6 +473,15 @@ public:
|
||||
const parametermap ¶meters,
|
||||
std::string &answer);
|
||||
|
||||
/*!
|
||||
* @brief Gets the header from the last answer.
|
||||
*
|
||||
* @param header The header to search
|
||||
*
|
||||
* @return The header, or "" on error.
|
||||
*/
|
||||
const std::string get_header(const std::string &header) const;
|
||||
|
||||
private:
|
||||
const std::string _instance;
|
||||
std::string _access_token;
|
||||
@ -531,10 +541,13 @@ private:
|
||||
const curlpp::Forms &formdata,
|
||||
std::string &answer);
|
||||
|
||||
const void get_headers(std::string &headers) const;
|
||||
|
||||
private:
|
||||
const API &parent;
|
||||
const std::string _instance;
|
||||
const std::string _access_token;
|
||||
std::string _headers;
|
||||
} _http;
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user