summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
Diffstat (limited to 'methods')
-rw-r--r--methods/basehttp.cc29
-rw-r--r--methods/basehttp.h1
2 files changed, 29 insertions, 1 deletions
diff --git a/methods/basehttp.cc b/methods/basehttp.cc
index 26b633cba..d335e6fa0 100644
--- a/methods/basehttp.cc
+++ b/methods/basehttp.cc
@@ -263,6 +263,21 @@ bool RequestState::HeaderLine(string const &Line) /*{{{*/
return true;
}
+ if (stringcasecmp(Tag, "Retry-After:") == 0)
+ {
+ unsigned long _retry_after_s;
+ if (RFC1123StrToTime(Val, RetryAfter))
+ {
+ return true;
+ }
+ if (StrToNum(Val.c_str(), _retry_after_s, 4, 10) == 1)
+ {
+ RetryAfter = time(nullptr) + _retry_after_s;
+ return true;
+ }
+ return _error->Error(_("Unknown date format"));
+ }
+
if (Server->RangesAllowed && stringcasecmp(Tag, "Via:") == 0)
{
auto const parts = VectorizeString(Val, ' ');
@@ -884,7 +899,19 @@ int BaseHttpMethod::Loop()
599, // Network Connect Timeout Error
};
if (std::find(std::begin(TransientCodes), std::end(TransientCodes), Req.Result) != std::end(TransientCodes))
- Fail(true);
+ {
+ if (Req.RetryAfter)
+ {
+ std::unordered_map<std::string, std::string> fields;
+ fields["Retry-After"] = std::to_string(Req.RetryAfter);
+ SetFailReason("TooManyRequests");
+ FailWithContext(std::string("TooManyRequests"), true, fields);
+ }
+ else
+ {
+ Fail(true);
+ }
+ }
else
Fail();
break;
diff --git a/methods/basehttp.h b/methods/basehttp.h
index 080ea527e..c077ea384 100644
--- a/methods/basehttp.h
+++ b/methods/basehttp.h
@@ -57,6 +57,7 @@ struct RequestState
enum {Chunked,Stream,Closes} Encoding = Closes;
enum {Header, Data} State = Header;
std::string Location;
+ time_t RetryAfter = 0;
FileFd File;