Allow to add Date header to the request.
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
+2
-2
@@ -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.
|
||||||
|
|||||||
+2
-1
@@ -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_;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -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_
|
||||||
|
|||||||
Reference in New Issue
Block a user