From 87e9bb3af7002cd70fcda48c4001690e4bda68a2 Mon Sep 17 00:00:00 2001 From: Thomas Droxler Date: Tue, 11 Aug 2026 11:08:45 +0200 Subject: [PATCH] Add `Cache-Control` header for charts and infos Resolves: #670 --- .../resources/explorer-backend-openapi.json | 64 +++++++++++++++++++ .../alephium/explorer/api/BaseEndpoint.scala | 3 + .../explorer/api/ChartsEndpoints.scala | 3 + .../explorer/api/InfosEndpoints.scala | 3 + 4 files changed, 73 insertions(+) diff --git a/app/src/main/resources/explorer-backend-openapi.json b/app/src/main/resources/explorer-backend-openapi.json index 139c4c96d..b5937a98c 100644 --- a/app/src/main/resources/explorer-backend-openapi.json +++ b/app/src/main/resources/explorer-backend-openapi.json @@ -5560,6 +5560,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "application/json": { "schema": { @@ -6072,6 +6080,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "text/plain": { "schema": { @@ -6172,6 +6188,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "text/plain": { "schema": { @@ -6272,6 +6296,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "text/plain": { "schema": { @@ -6372,6 +6404,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "text/plain": { "schema": { @@ -7000,6 +7040,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "application/json": { "schema": { @@ -7146,6 +7194,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "application/json": { "schema": { @@ -7290,6 +7346,14 @@ "responses": { "200": { "description": "Ok", + "headers": { + "Cache-Control": { + "required": true, + "schema": { + "type": "string" + } + } + }, "content": { "application/json": { "schema": { diff --git a/app/src/main/scala/org/alephium/explorer/api/BaseEndpoint.scala b/app/src/main/scala/org/alephium/explorer/api/BaseEndpoint.scala index 727eb7d6f..4abadb683 100644 --- a/app/src/main/scala/org/alephium/explorer/api/BaseEndpoint.scala +++ b/app/src/main/scala/org/alephium/explorer/api/BaseEndpoint.scala @@ -43,6 +43,9 @@ trait BaseEndpoint extends ErrorExamples with TapirCodecs with TapirSchemasLike ) ) + def cacheControl(maxAgeSeconds: Int): EndpointIO.FixedHeader[Unit] = + header("Cache-Control", s"public, max-age=$maxAgeSeconds") + def arrayBody[T](tpe: String, maxSize: Int)(implicit examples: List[Example[ArraySeq[T]]], rw: ReadWriter[ArraySeq[T]], diff --git a/app/src/main/scala/org/alephium/explorer/api/ChartsEndpoints.scala b/app/src/main/scala/org/alephium/explorer/api/ChartsEndpoints.scala index 50b887856..055cd4c35 100644 --- a/app/src/main/scala/org/alephium/explorer/api/ChartsEndpoints.scala +++ b/app/src/main/scala/org/alephium/explorer/api/ChartsEndpoints.scala @@ -18,10 +18,13 @@ trait ChartsEndpoints extends BaseEndpoint with QueryParams { val intervalTypes: String = IntervalType.all.dropRight(1).map(_.string).mkString(", ") + private val chartCacheMaxAgeSeconds = 60 + private val chartsEndpoint = baseEndpoint .tag("Charts") .in("charts") + .out(cacheControl(chartCacheMaxAgeSeconds)) val getHashrates: BaseEndpoint[(TimeInterval, IntervalType), ArraySeq[Hashrate]] = chartsEndpoint.get diff --git a/app/src/main/scala/org/alephium/explorer/api/InfosEndpoints.scala b/app/src/main/scala/org/alephium/explorer/api/InfosEndpoints.scala index 366bb7625..6cd86c66e 100644 --- a/app/src/main/scala/org/alephium/explorer/api/InfosEndpoints.scala +++ b/app/src/main/scala/org/alephium/explorer/api/InfosEndpoints.scala @@ -22,9 +22,12 @@ trait InfosEndpoints extends BaseEndpoint with QueryParams { .tag("Infos") .in("infos") + private val infoCacheMaxAgeSeconds = 30 + private val supplyEndpoint = infosEndpoint .in("supply") + .out(cacheControl(infoCacheMaxAgeSeconds)) val getInfos: BaseEndpoint[Unit, ExplorerInfo] = infosEndpoint.get