Enable access to HTTP headers

This commit is contained in:
tastytea 2018-02-25 23:20:02 +01:00
parent 233cb04268
commit f9b6009b57
Signed by: tastytea
GPG Key ID: 59346E0EA35C67E5
6 changed files with 95 additions and 3 deletions

View File

@ -1,6 +1,6 @@
cmake_minimum_required (VERSION 3.7)
project (mastodon-cpp
VERSION 0.3.2
VERSION 0.3.3
LANGUAGES CXX
)

View File

@ -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

View 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;
}

View File

@ -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;
}

View File

@ -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 "";
}

View File

@ -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 &parameters,
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;
};
}