Line data Source code
1 : #include "source/common/router/reset_header_parser.h" 2 : 3 : #include <cstdint> 4 : 5 : #include "source/common/common/assert.h" 6 : 7 : #include "absl/strings/numbers.h" 8 : 9 : namespace Envoy { 10 : namespace Router { 11 : 12 : ResetHeaderParserImpl::ResetHeaderParserImpl( 13 : const envoy::config::route::v3::RetryPolicy::ResetHeader& config) 14 0 : : name_(config.name()) { 15 0 : switch (config.format()) { 16 0 : PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; 17 0 : case envoy::config::route::v3::RetryPolicy::SECONDS: 18 0 : format_ = ResetHeaderFormat::Seconds; 19 0 : break; 20 0 : case envoy::config::route::v3::RetryPolicy::UNIX_TIMESTAMP: 21 0 : format_ = ResetHeaderFormat::UnixTimestamp; 22 0 : break; 23 0 : } 24 0 : } 25 : 26 : absl::optional<std::chrono::milliseconds> 27 : ResetHeaderParserImpl::parseInterval(TimeSource& time_source, 28 0 : const Http::HeaderMap& headers) const { 29 0 : const auto header = headers.get(name_); 30 : 31 0 : if (header.empty()) { 32 0 : return absl::nullopt; 33 0 : } 34 : 35 : // This is effectively a trusted header so per the API only using the first value is used. 36 0 : const auto& header_value = header[0]->value().getStringView(); 37 0 : uint64_t num_seconds{}; 38 : 39 0 : switch (format_) { 40 0 : case ResetHeaderFormat::Seconds: 41 0 : if (absl::SimpleAtoi(header_value, &num_seconds)) { 42 0 : return absl::optional<std::chrono::milliseconds>(num_seconds * 1000UL); 43 0 : } 44 0 : break; 45 : 46 0 : case ResetHeaderFormat::UnixTimestamp: 47 0 : if (absl::SimpleAtoi(header_value, &num_seconds)) { 48 0 : const uint64_t timestamp = DateUtil::nowToSeconds(time_source); 49 : 50 0 : if (num_seconds < timestamp) { 51 0 : return absl::nullopt; 52 0 : } 53 : 54 0 : const uint64_t interval = num_seconds - timestamp; 55 0 : return absl::optional<std::chrono::milliseconds>(interval * 1000UL); 56 0 : } 57 0 : break; 58 0 : } 59 : 60 0 : return absl::nullopt; 61 0 : } 62 : 63 : } // namespace Router 64 : } // namespace Envoy