Skip to content

Commit

Permalink
Allow custom headers to be returned as part of pre-flight requests
Browse files Browse the repository at this point in the history
  • Loading branch information
miike committed Apr 17, 2024
1 parent df59504 commit 2d7a3c8
Show file tree
Hide file tree
Showing 16 changed files with 32 additions and 9 deletions.
1 change: 1 addition & 0 deletions core/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

cors {
accessControlMaxAge = 60 minutes
allowedCorsHeaders = ["X-Example"]
}

streams {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ object Config {
)

case class CORS(
accessControlMaxAge: FiniteDuration
accessControlMaxAge: FiniteDuration,
allowedCorsHeaders: List[String]
)

case class Streams[+SinkConfig](
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import org.apache.commons.codec.binary.Base64
import scala.concurrent.duration._
import scala.jdk.CollectionConverters._

import cats.data.NonEmptyList
import cats.effect.{Clock, Sync}
import cats.implicits._

Expand Down Expand Up @@ -139,11 +140,13 @@ class Service[F[_]: Sync](
}

override def preflightResponse(req: Request[F]): F[Response[F]] = Sync[F].pure {
val allowedHeaders = (List("Content-Type", "SP-Anonymous") ++ config.cors.allowedCorsHeaders).map(CIString(_))
val corsHeaders = NonEmptyList.fromListUnsafe(allowedHeaders)
Response[F](
headers = Headers(
accessControlAllowOriginHeader(req),
`Access-Control-Allow-Credentials`(),
`Access-Control-Allow-Headers`(ci"Content-Type", ci"SP-Anonymous"),
`Access-Control-Allow-Headers`(corsHeaders),
`Access-Control-Max-Age`.Cache(config.cors.accessControlMaxAge.toSeconds).asInstanceOf[`Access-Control-Max-Age`]
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ class ServiceSpec extends Specification {
val expected = Headers(
Header.Raw(ci"Access-Control-Allow-Origin", "*"),
`Access-Control-Allow-Credentials`(),
`Access-Control-Allow-Headers`(ci"Content-Type", ci"SP-Anonymous"),
`Access-Control-Allow-Headers`(ci"Content-Type", ci"SP-Anonymous", ci"X-Howdy"),
`Access-Control-Max-Age`.Cache(3600).asInstanceOf[`Access-Control-Max-Age`]
)
service.preflightResponse(Request[IO]()).unsafeRunSync().headers shouldEqual expected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ object TestUtils {
Map.empty[String, String],
""
),
cors = CORS(60.minutes),
cors = CORS(60.minutes, List("X-Howdy")),
streams = Streams(
good = SinkConfig(
name = "raw",
Expand Down
3 changes: 3 additions & 0 deletions examples/config.kafka.extended.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ collector {
# The Access-Control-Max-Age response header indicates how long the results of a preflight
# request can be cached. -1 seconds disables the cache. Chromium max is 10m, Firefox is 24h.
accessControlMaxAge = 60 minutes
# The allowedCorsHeaders response header allows non-safelisted CORS headers to be returned
# as part of OPTIONS (preflight) requests
allowedCorsHeaders = ["X-Example"]
}

streams {
Expand Down
3 changes: 3 additions & 0 deletions examples/config.kinesis.extended.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ collector {
# The Access-Control-Max-Age response header indicates how long the results of a preflight
# request can be cached. -1 seconds disables the cache. Chromium max is 10m, Firefox is 24h.
accessControlMaxAge = 60 minutes
# The allowedCorsHeaders response header allows non-safelisted CORS headers to be returned
# as part of OPTIONS (preflight) requests
allowedCorsHeaders = ["X-Example"]
}

streams {
Expand Down
3 changes: 3 additions & 0 deletions examples/config.nsq.extended.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ collector {
# The Access-Control-Max-Age response header indicates how long the results of a preflight
# request can be cached. -1 seconds disables the cache. Chromium max is 10m, Firefox is 24h.
accessControlMaxAge = 60 minutes
# The allowedCorsHeaders response header allows non-safelisted CORS headers to be returned
# as part of OPTIONS (preflight) requests
allowedCorsHeaders = ["X-Example"]
}

streams {
Expand Down
3 changes: 3 additions & 0 deletions examples/config.pubsub.extended.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ collector {
# The Access-Control-Max-Age response header indicates how long the results of a preflight
# request can be cached. -1 seconds disables the cache. Chromium max is 10m, Firefox is 24h.
accessControlMaxAge = 60 minutes
# The allowedCorsHeaders response header allows non-safelisted CORS headers to be returned
# as part of OPTIONS (preflight) requests
allowedCorsHeaders = ["X-Example"]
}

streams {
Expand Down
3 changes: 3 additions & 0 deletions examples/config.sqs.extended.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ collector {
# The Access-Control-Max-Age response header indicates how long the results of a preflight
# request can be cached. -1 seconds disables the cache. Chromium max is 10m, Firefox is 24h.
accessControlMaxAge = 60 minutes
# The allowedCorsHeaders response header allows non-safelisted CORS headers to be returned
# as part of OPTIONS (preflight) requests
allowedCorsHeaders = ["X-Example"]
}

streams {
Expand Down
3 changes: 3 additions & 0 deletions examples/config.stdout.extended.hocon
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ collector {
# The Access-Control-Max-Age response header indicates how long the results of a preflight
# request can be cached. -1 seconds disables the cache. Chromium max is 10m, Firefox is 24h.
accessControlMaxAge = 60 minutes
# The allowedCorsHeaders response header allows non-safelisted CORS headers to be returned
# as part of OPTIONS (preflight) requests
allowedCorsHeaders = ["X-Example"]
}

streams {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ object KafkaConfigSpec {
headers = Map.empty[String, String],
body = ""
),
cors = Config.CORS(1.hour),
cors = Config.CORS(1.hour, List("X-Howdy")),
monitoring = Config.Monitoring(
Config.Metrics(
Config.Statsd(false, "localhost", 8125, 10.seconds, "snowplow.collector", Map.empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ object KinesisConfigSpec {
headers = Map.empty[String, String],
body = ""
),
cors = Config.CORS(1.hour),
cors = Config.CORS(1.hour, List("X-Howdy")),
monitoring = Config.Monitoring(
Config.Metrics(
Config.Statsd(false, "localhost", 8125, 10.seconds, "snowplow.collector", Map.empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ object NsqConfigSpec {
headers = Map.empty[String, String],
body = ""
),
cors = Config.CORS(1.hour),
cors = Config.CORS(1.hour, List("X-Howdy")),
monitoring = Config.Monitoring(
Config.Metrics(
Config.Statsd(false, "localhost", 8125, 10.seconds, "snowplow.collector", Map.empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ object ConfigSpec {
headers = Map.empty[String, String],
body = ""
),
cors = Config.CORS(1.hour),
cors = Config.CORS(1.hour, List("X-Howdy")),
monitoring = Config.Monitoring(
Config.Metrics(
Config.Statsd(false, "localhost", 8125, 10.seconds, "snowplow.collector", Map.empty)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ object SqsConfigSpec {
headers = Map.empty[String, String],
body = ""
),
cors = Config.CORS(1.hour),
cors = Config.CORS(1.hour, List("X-Howdy")),
monitoring = Config.Monitoring(
Config.Metrics(
Config.Statsd(false, "localhost", 8125, 10.seconds, "snowplow.collector", Map.empty)
Expand Down

0 comments on commit 2d7a3c8

Please sign in to comment.