Allow to add Date header to the request.

master
Chunting Gu 6 years ago
parent 7af95778f5
commit 22b209d13e

@ -31,6 +31,7 @@ int main() {
Url("http://httpbin.org/get"). Url("http://httpbin.org/get").
Query("key1", "value1"). Query("key1", "value1").
Query("key2", "value2"). Query("key2", "value2").
Date().
Header("Accept", "application/json") Header("Accept", "application/json")
()); ());

@ -8,7 +8,7 @@ TEST(UtilityTest, SplitKV) {
std::string key; std::string key;
std::string value; std::string value;
bool ok = webcc::SplitKV(str, ':', &key, &value); bool ok = webcc::utility::SplitKV(str, ':', &key, &value);
EXPECT_EQ(true, ok); EXPECT_EQ(true, ok);
EXPECT_EQ("Connection", key); EXPECT_EQ("Connection", key);

@ -3,6 +3,7 @@
#include "webcc/base64.h" #include "webcc/base64.h"
#include "webcc/logger.h" #include "webcc/logger.h"
#include "webcc/url.h" #include "webcc/url.h"
#include "webcc/utility.h"
namespace webcc { namespace webcc {
@ -124,7 +125,7 @@ ResponsePtr ClientSession::Patch(const std::string& url, std::string&& data,
void ClientSession::InitHeaders() { void ClientSession::InitHeaders() {
using namespace headers; using namespace headers;
headers_.Set(kUserAgent, UserAgent()); headers_.Set(kUserAgent, utility::UserAgent());
// Content-Encoding Tokens: // Content-Encoding Tokens:
// (https://en.wikipedia.org/wiki/HTTP_compression) // (https://en.wikipedia.org/wiki/HTTP_compression)

@ -98,7 +98,7 @@ std::vector<Header>::iterator Headers::Find(const std::string& key) {
static bool ParseValue(const std::string& str, const std::string& expected_key, static bool ParseValue(const std::string& str, const std::string& expected_key,
std::string* value) { std::string* value) {
std::string key; std::string key;
if (!SplitKV(str, '=', &key, value)) { if (!utility::SplitKV(str, '=', &key, value)) {
return false; return false;
} }
@ -182,7 +182,7 @@ bool ContentDisposition::Init(const std::string& str) {
std::string key; std::string key;
std::string value; std::string value;
for (std::size_t i = 1; i < parts.size(); ++i) { for (std::size_t i = 1; i < parts.size(); ++i) {
if (!SplitKV(parts[i], '=', &key, &value)) { if (!utility::SplitKV(parts[i], '=', &key, &value)) {
return false; return false;
} }

@ -8,11 +8,6 @@ namespace webcc {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
const std::string& UserAgent() {
static std::string s_user_agent = std::string("Webcc/") + WEBCC_VERSION;
return s_user_agent;
}
namespace media_types { namespace media_types {
// TODO: Add more. // TODO: Add more.

@ -38,8 +38,6 @@
#endif // _MSC_VER #endif // _MSC_VER
#define ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A)))
namespace webcc { namespace webcc {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -149,9 +147,6 @@ enum class ContentEncoding {
kDeflate, kDeflate,
}; };
// Return default user agent for HTTP headers.
const std::string& UserAgent();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Client side error codes. // Client side error codes.

@ -49,7 +49,7 @@ bool Compress(const std::string& input, std::string* output) {
} }
std::size_t size = buf.size() - stream.avail_out; std::size_t size = buf.size() - stream.avail_out;
output->insert(output->end(), buf.data(), buf.data() + size); output->append(buf.data(), size);
} while (stream.avail_out == 0); } while (stream.avail_out == 0);
@ -106,6 +106,7 @@ bool Decompress(const std::string& input, std::string* output) {
if (err == Z_STREAM_END) { if (err == Z_STREAM_END) {
break; break;
} }
if (err != Z_OK) { if (err != Z_OK) {
inflateEnd(&stream); inflateEnd(&stream);
if (stream.msg != nullptr) { if (stream.msg != nullptr) {

@ -1,7 +1,5 @@
#include "webcc/message.h" #include "webcc/message.h"
#include <ctime>
#include <iomanip> // for put_time
#include <sstream> #include <sstream>
#include "boost/algorithm/string.hpp" #include "boost/algorithm/string.hpp"
@ -181,11 +179,4 @@ std::string Message::Dump(std::size_t indent,
return ss.str(); return ss.str();
} }
std::string Message::GetTimestamp() {
std::time_t t = std::time(nullptr);
std::stringstream ss;
ss << std::put_time(std::gmtime(&t), "%a, %d %b %Y %H:%M:%S") << " GMT";
return ss.str();
}
} // namespace webcc } // namespace webcc

@ -112,11 +112,6 @@ protected:
SetHeader(headers::kContentLength, std::to_string(content_length)); SetHeader(headers::kContentLength, std::to_string(content_length));
} }
// Get the timestamp for HTTP Date header field.
// E.g., Wed, 21 Oct 2015 07:28:00 GMT
// See: https://tools.ietf.org/html/rfc7231#section-7.1.1.2
std::string GetTimestamp();
protected: protected:
std::string start_line_; std::string start_line_;

@ -138,7 +138,7 @@ bool Parser::GetNextLine(std::size_t off, std::string* line, bool erase) {
bool Parser::ParseHeaderLine(const std::string& line) { bool Parser::ParseHeaderLine(const std::string& line) {
Header header; Header header;
if (!SplitKV(line, ':', &header.first, &header.second)) { if (!utility::SplitKV(line, ':', &header.first, &header.second)) {
LOG_ERRO("Invalid header: %s", line.c_str()); LOG_ERRO("Invalid header: %s", line.c_str());
return false; return false;
} }

@ -37,7 +37,7 @@ void Request::Prepare() {
// Another choice to generate the boundary is like what Apache does. // Another choice to generate the boundary is like what Apache does.
// See: https://stackoverflow.com/a/5686863 // See: https://stackoverflow.com/a/5686863
if (boundary_.empty()) { if (boundary_.empty()) {
boundary_ = RandomUuid(); boundary_ = utility::RandomUuid();
} }
SetContentType("multipart/form-data; boundary=" + boundary_); SetContentType("multipart/form-data; boundary=" + boundary_);

@ -78,6 +78,12 @@ RequestBuilder& RequestBuilder::AuthToken(const std::string& token) {
return Auth("Token", token); return Auth("Token", token);
} }
RequestBuilder& RequestBuilder::Date() {
headers_.push_back(headers::kDate);
headers_.push_back(utility::GetTimestamp());
return *this;
}
void RequestBuilder::SetContent(RequestPtr request, std::string&& data) { void RequestBuilder::SetContent(RequestPtr request, std::string&& data) {
#if WEBCC_ENABLE_GZIP #if WEBCC_ENABLE_GZIP
if (gzip_ && data.size() > kGzipThreshold) { if (gzip_ && data.size() > kGzipThreshold) {

@ -96,6 +96,9 @@ public:
RequestBuilder& AuthToken(const std::string& token); RequestBuilder& AuthToken(const std::string& token);
// Add the Date header to the request.
RequestBuilder& Date();
private: private:
void SetContent(RequestPtr request, std::string&& data); void SetContent(RequestPtr request, std::string&& data);

@ -167,7 +167,7 @@ bool RequestParser::ParsePartHeaders(bool* need_more_data) {
} }
Header header; Header header;
if (!SplitKV(line, ':', &header.first, &header.second)) { if (!utility::SplitKV(line, ':', &header.first, &header.second)) {
LOG_ERRO("Invalid part header line: %s", line.c_str()); LOG_ERRO("Invalid part header line: %s", line.c_str());
return false; return false;
} }

@ -1,12 +1,14 @@
#include "webcc/response.h" #include "webcc/response.h"
#include "webcc/utility.h"
namespace webcc { namespace webcc {
void Response::Prepare() { void Response::Prepare() {
PrepareStatusLine(); PrepareStatusLine();
SetHeader(headers::kServer, UserAgent()); SetHeader(headers::kServer, utility::UserAgent());
SetHeader(headers::kDate, GetTimestamp()); SetHeader(headers::kDate, utility::GetTimestamp());
Message::Prepare(); Message::Prepare();
} }

@ -1,12 +1,17 @@
#include "webcc/utility.h" #include "webcc/utility.h"
#include <ctime>
#include <iomanip> // for put_time
#include <sstream> #include <sstream>
#include "boost/algorithm/string.hpp" #include "boost/algorithm/string.hpp"
#include "boost/uuid/random_generator.hpp" #include "boost/uuid/random_generator.hpp"
#include "boost/uuid/uuid_io.hpp" #include "boost/uuid/uuid_io.hpp"
#include "webcc/version.h"
namespace webcc { namespace webcc {
namespace utility {
std::string RandomUuid() { std::string RandomUuid() {
boost::uuids::uuid u = boost::uuids::random_generator()(); boost::uuids::uuid u = boost::uuids::random_generator()();
@ -15,6 +20,18 @@ std::string RandomUuid() {
return ss.str(); return ss.str();
} }
const std::string& UserAgent() {
static auto s_user_agent = std::string("Webcc/") + WEBCC_VERSION;
return s_user_agent;
}
std::string GetTimestamp() {
std::time_t t = std::time(nullptr);
std::stringstream ss;
ss << std::put_time(std::gmtime(&t), "%a, %d %b %Y %H:%M:%S") << " GMT";
return ss.str();
}
bool SplitKV(const std::string& str, char delimiter, bool SplitKV(const std::string& str, char delimiter,
std::string* part1, std::string* part2) { std::string* part1, std::string* part2) {
std::size_t pos = str.find(delimiter); std::size_t pos = str.find(delimiter);
@ -31,4 +48,5 @@ bool SplitKV(const std::string& str, char delimiter,
return true; return true;
} }
} // namespace utility
} // namespace webcc } // namespace webcc

@ -4,14 +4,25 @@
#include <string> #include <string>
namespace webcc { namespace webcc {
namespace utility {
// Get a randomly generated UUID.
std::string RandomUuid(); std::string RandomUuid();
// Get default user agent for HTTP headers.
const std::string& UserAgent();
// Get the timestamp for HTTP Date header field.
// E.g., Wed, 21 Oct 2015 07:28:00 GMT
// See: https://tools.ietf.org/html/rfc7231#section-7.1.1.2
std::string GetTimestamp();
// Split a key-value string. // Split a key-value string.
// E.g., split "Connection: Keep-Alive". // E.g., split "Connection: Keep-Alive".
bool SplitKV(const std::string& str, char delimiter, bool SplitKV(const std::string& str, char delimiter,
std::string* key, std::string* value); std::string* key, std::string* value);
} // namespace utility
} // namespace webcc } // namespace webcc
#endif // WEBCC_UTILITY_H_ #endif // WEBCC_UTILITY_H_

Loading…
Cancel
Save