mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 11:27:05 +00:00
Using UTC and per hour for Rate Limiting
This commit is contained in:
parent
efc1868fd4
commit
284743da16
@ -2848,9 +2848,9 @@ Query active rate limits for a specific hour:
|
||||
GET /obp/v6.0.0/management/consumers/CONSUMER_ID/active-rate-limits/DATE_WITH_HOUR
|
||||
```
|
||||
|
||||
Where `DATE_WITH_HOUR` is in format `YYYY-MM-DD-HH` (e.g., `2025-12-31-13` for hour 13:00-13:59 on Dec 31, 2025).
|
||||
Where `DATE_WITH_HOUR` is in format `YYYY-MM-DD-HH` in **UTC timezone** (e.g., `2025-12-31-13` for hour 13:00-13:59 UTC on Dec 31, 2025).
|
||||
|
||||
Rate limits are cached and queried at hour-level granularity for performance.
|
||||
Rate limits are cached and queried at hour-level granularity for performance. All hours are interpreted in UTC for consistency.
|
||||
|
||||
**Rate Limit Headers:**
|
||||
|
||||
|
||||
@ -303,11 +303,11 @@ object Glossary extends MdcLoggable {
|
||||
|GET /obp/v6.0.0/management/consumers/{CONSUMER_ID}/active-rate-limits/{DATE_WITH_HOUR}
|
||||
|```
|
||||
|
|
||||
|Where `DATE_WITH_HOUR` is in format `YYYY-MM-DD-HH` (e.g., `2025-12-31-13` for hour 13:00-13:59 on Dec 31, 2025).
|
||||
|Where `DATE_WITH_HOUR` is in format `YYYY-MM-DD-HH` in **UTC timezone** (e.g., `2025-12-31-13` for hour 13:00-13:59 UTC on Dec 31, 2025).
|
||||
|
|
||||
|Returns the aggregated active rate limits for the specified hour, including which rate limit records contributed to the totals.
|
||||
|
|
||||
|Rate limits are cached and queried at hour-level granularity for performance.
|
||||
|Rate limits are cached and queried at hour-level granularity for performance. All hours are interpreted in UTC for consistency across all servers.
|
||||
|
|
||||
|### System Defaults
|
||||
|
|
||||
|
||||
@ -469,7 +469,9 @@ trait APIMethods600 {
|
||||
|
|
||||
|See ${Glossary.getGlossaryItemLink("Rate Limiting")} for more details on how rate limiting works.
|
||||
|
|
||||
|Date format: YYYY-MM-DD-HH (e.g. 2025-12-31-13 for hour 13:00-13:59 on Dec 31, 2025)
|
||||
|Date format: YYYY-MM-DD-HH in UTC timezone (e.g. 2025-12-31-13 for hour 13:00-13:59 UTC on Dec 31, 2025)
|
||||
|
|
||||
|Note: The hour is always interpreted in UTC for consistency across all servers.
|
||||
|
|
||||
|${userAuthenticationMessage(true)}
|
||||
|
|
||||
@ -496,7 +498,7 @@ trait APIMethods600 {
|
||||
(Full(u), callContext) <- authenticatedAccess(cc)
|
||||
_ <- NewStyle.function.hasEntitlement("", u.userId, canGetRateLimits, callContext)
|
||||
_ <- NewStyle.function.getConsumerByConsumerId(consumerId, callContext)
|
||||
date <- NewStyle.function.tryons(s"$InvalidDateFormat Current date format is: $dateWithHourString. Please use this format: YYYY-MM-DD-HH (e.g. 2025-12-31-13 for hour 13 on Dec 31, 2025)", 400, callContext) {
|
||||
date <- NewStyle.function.tryons(s"$InvalidDateFormat Current date format is: $dateWithHourString. Please use this format: YYYY-MM-DD-HH in UTC (e.g. 2025-12-31-13 for hour 13:00-13:59 UTC on Dec 31, 2025)", 400, callContext) {
|
||||
val formatter = java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd-HH")
|
||||
val localDateTime = java.time.LocalDateTime.parse(dateWithHourString, formatter)
|
||||
java.util.Date.from(localDateTime.atZone(java.time.ZoneOffset.UTC).toInstant())
|
||||
|
||||
@ -264,15 +264,16 @@ object MappedRateLimitingProvider extends RateLimitingProviderTrait with Logger
|
||||
private def getActiveCallLimitsByConsumerIdAtDateCached(consumerId: String, dateWithHour: String): List[RateLimiting] = {
|
||||
// Cache key uses standardized prefix: rl_active_{consumerId}_{dateWithHour}
|
||||
// Create Date objects for start and end of the hour from the date_with_hour string
|
||||
// IMPORTANT: Hour format is in UTC for consistency across all servers
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH")
|
||||
val localDateTime = LocalDateTime.parse(dateWithHour, formatter)
|
||||
|
||||
// Start of hour: 00 mins, 00 seconds
|
||||
// Start of hour: 00 mins, 00 seconds (UTC)
|
||||
val startOfHour = localDateTime.withMinute(0).withSecond(0)
|
||||
val startInstant = startOfHour.atZone(java.time.ZoneOffset.UTC).toInstant()
|
||||
val startDate = Date.from(startInstant)
|
||||
|
||||
// End of hour: 59 mins, 59 seconds
|
||||
// End of hour: 59 mins, 59 seconds (UTC)
|
||||
val endOfHour = localDateTime.withMinute(59).withSecond(59)
|
||||
val endInstant = endOfHour.atZone(java.time.ZoneOffset.UTC).toInstant()
|
||||
val endDate = Date.from(endInstant)
|
||||
@ -292,10 +293,11 @@ object MappedRateLimitingProvider extends RateLimitingProviderTrait with Logger
|
||||
}
|
||||
}
|
||||
|
||||
def getActiveCallLimitsByConsumerIdAtDate(consumerId: String, date: Date): Future[List[RateLimiting]] = Future {
|
||||
def getActiveCallLimitsByConsumerIdAtDate(consumerId: String, dateUtc: Date): Future[List[RateLimiting]] = Future {
|
||||
// Convert the provided date parameter (not current time!) to hour format
|
||||
// Date is timezone-agnostic (millis since epoch), we interpret it as UTC
|
||||
def dateWithHour: String = {
|
||||
val instant = date.toInstant()
|
||||
val instant = dateUtc.toInstant()
|
||||
val localDateTime = LocalDateTime.ofInstant(instant, java.time.ZoneOffset.UTC)
|
||||
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH")
|
||||
localDateTime.format(formatter)
|
||||
|
||||
@ -56,7 +56,7 @@ trait RateLimitingProviderTrait {
|
||||
perMonth: Option[String]): Future[Box[RateLimiting]]
|
||||
def deleteByRateLimitingId(rateLimitingId: String): Future[Box[Boolean]]
|
||||
def getByRateLimitingId(rateLimitingId: String): Future[Box[RateLimiting]]
|
||||
def getActiveCallLimitsByConsumerIdAtDate(consumerId: String, date: Date): Future[List[RateLimiting]]
|
||||
def getActiveCallLimitsByConsumerIdAtDate(consumerId: String, dateUtc: Date): Future[List[RateLimiting]]
|
||||
}
|
||||
|
||||
trait RateLimitingTrait {
|
||||
|
||||
@ -26,7 +26,7 @@ TESOBE (http://www.tesobe.com/)
|
||||
package code.api.v6_0_0
|
||||
|
||||
import code.api.util.APIUtil.OAuth._
|
||||
import code.api.util.ApiRole.{CanDeleteRateLimits, CanGetRateLimits, CanCreateRateLimits}
|
||||
import code.api.util.ApiRole.{CanCreateRateLimits, CanDeleteRateLimits, CanGetRateLimits}
|
||||
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
|
||||
import code.api.v6_0_0.OBPAPI6_0_0.Implementations6_0_0
|
||||
import code.consumer.Consumers
|
||||
|
||||
Loading…
Reference in New Issue
Block a user