Skip to content

Commit

Permalink
Fixed issues created by the date string being localized (#2217)
Browse files Browse the repository at this point in the history
  • Loading branch information
easymoney322 authored Dec 5, 2024
1 parent 1765223 commit 3e944d2
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 8 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@ jobs:
sudo apt-get install -y libjsoncpp-dev uuid-dev libssl-dev zlib1g-dev libsqlite3-dev
sudo apt-get install -y ninja-build libbrotli-dev
sudo apt-get install -y libspdlog-dev
- name: Install and update locales
run: |
sudo apt-get install -y locales
sudo locale-gen en_US && sudo locale-gen en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8
- name: Install postgresql
run: |
Expand Down
6 changes: 6 additions & 0 deletions lib/inc/drogon/utils/Utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,12 @@ DROGON_EXPORT std::string brotliDecompress(const char *data,
DROGON_EXPORT char *getHttpFullDate(
const trantor::Date &date = trantor::Date::now());

DROGON_EXPORT const std::string &getHttpFullDateStr(
const trantor::Date &date = trantor::Date::now());

DROGON_EXPORT void dateToCustomFormattedString(const std::string &fmtStr,
std::string &str,
const trantor::Date &date);
/// Get the trantor::Date object according to the http full date string
/**
* Returns trantor::Date(std::numeric_limits<int64_t>::max()) upon failure.
Expand Down
2 changes: 1 addition & 1 deletion lib/src/Cookie.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ std::string Cookie::cookieString() const
expiresDate_.microSecondsSinceEpoch() >= 0)
{
ret.append("Expires=")
.append(utils::getHttpFullDate(expiresDate_))
.append(utils::getHttpFullDateStr(expiresDate_))
.append("; ");
}
if (maxAge_.has_value())
Expand Down
6 changes: 2 additions & 4 deletions lib/src/HttpResponseImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,7 @@ void HttpResponseImpl::renderToBuffer(trantor::MsgBuffer &buffer)
drogon::HttpAppFrameworkImpl::instance().sendDateHeader())
{
buffer.append("date: ");
buffer.append(utils::getHttpFullDate(trantor::Date::date()),
httpFullDateStringLength);
buffer.append(utils::getHttpFullDateStr(trantor::Date::date()));
buffer.append("\r\n\r\n");
}
else
Expand Down Expand Up @@ -706,8 +705,7 @@ std::shared_ptr<trantor::MsgBuffer> HttpResponseImpl::renderToBuffer()
{
httpString->append("date: ");
auto datePos = httpString->readableBytes();
httpString->append(utils::getHttpFullDate(trantor::Date::date()),
httpFullDateStringLength);
httpString->append(utils::getHttpFullDateStr(trantor::Date::date()));
httpString->append("\r\n\r\n");
datePos_ = datePos;
}
Expand Down
29 changes: 29 additions & 0 deletions lib/src/Utilities.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,35 @@ char *getHttpFullDate(const trantor::Date &date)
return lastTimeString;
}

void dateToCustomFormattedString(const std::string &fmtStr,
std::string &str,
const trantor::Date &date)
{
auto nowSecond = date.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC;
time_t seconds = static_cast<time_t>(nowSecond);
struct tm tm_LValue = date.tmStruct();
std::stringstream Out;
Out.imbue(std::locale{"en_US"});

This comment has been minimized.

Copy link
@GladBarsan

GladBarsan Dec 7, 2024

Should be en_US.UTF-8

Out << std::put_time(&tm_LValue, fmtStr.c_str());
str = Out.str();
}

const std::string &getHttpFullDateStr(const trantor::Date &date)
{
static thread_local int64_t lastSecond = 0;
static thread_local std::string lastTimeString(128, 0);
auto nowSecond = date.microSecondsSinceEpoch() / MICRO_SECONDS_PRE_SEC;
if (nowSecond == lastSecond)
{
return lastTimeString;
}
lastSecond = nowSecond;
dateToCustomFormattedString("%a, %d %b %Y %H:%M:%S GMT",
lastTimeString,
date);
return lastTimeString;
}

trantor::Date getHttpDate(const std::string &httpFullDateString)
{
static const std::array<const char *, 4> formats = {
Expand Down
3 changes: 1 addition & 2 deletions lib/tests/integration_test/server/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -408,8 +408,7 @@ int main()
app().registerCustomExtensionMime("md", "text/markdown");
app().setFileTypes({"md", "html", "jpg", "cc", "txt"});
std::cout << "Date: "
<< std::string{drogon::utils::getHttpFullDate(
trantor::Date::now())}
<< drogon::utils::getHttpFullDateStr(trantor::Date::now())
<< std::endl;

app().registerBeginningAdvice(
Expand Down
2 changes: 1 addition & 1 deletion lib/tests/unittests/HttpFullDateTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ using namespace drogon;

DROGON_TEST(HttpFullDateTest)
{
auto str = utils::getHttpFullDate();
auto str = utils::getHttpFullDateStr();
auto date = utils::getHttpDate(str);
CHECK(utils::getHttpFullDate(date) == str);
}

1 comment on commit 3e944d2

@GladBarsan
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heyo
Out.imbue(std::locale{"en_US"}); should be en_US.UTF-8
This causes the server to crash on any request with Exception thrown from event loop, rethrowing after running functions on quit: locale::facet::_S_create_c_locale name not valid - EventLoop.cc:244

Please sign in to comment.