From 55c57c487e4e71bf682281ab839b58d5888a92b8 Mon Sep 17 00:00:00 2001 From: user411 Date: Fri, 27 Aug 2021 06:57:36 -0600 Subject: [PATCH] Add CORS handling for running from a local dev server (#3612) --- .../bitcoins/server/routes/CORSHandler.scala | 45 +++++++++++++++++++ .../org/bitcoins/server/routes/Server.scala | 5 ++- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 app/server-routes/src/main/scala/org/bitcoins/server/routes/CORSHandler.scala diff --git a/app/server-routes/src/main/scala/org/bitcoins/server/routes/CORSHandler.scala b/app/server-routes/src/main/scala/org/bitcoins/server/routes/CORSHandler.scala new file mode 100644 index 0000000000..0cde6f62f1 --- /dev/null +++ b/app/server-routes/src/main/scala/org/bitcoins/server/routes/CORSHandler.scala @@ -0,0 +1,45 @@ +package org.bitcoins.server.routes + +import akka.http.scaladsl.model.{HttpResponse, StatusCodes} +import akka.http.scaladsl.model.headers._ +import akka.http.scaladsl.model.HttpMethods._ +import akka.http.scaladsl.server.Directive0 +import akka.http.scaladsl.server.Directives._ +import akka.http.scaladsl.server.Route + +/** Add CORS handling for accessing backend over localhost from modern browsers + * @see dzone.com/articles/handling-cors-in-akka-http + */ +trait CORSHandler { + + private val corsResponseHeaders = List( + `Access-Control-Allow-Origin`.*, + `Access-Control-Allow-Credentials`(true), + `Access-Control-Allow-Headers`("Authorization", + "Content-Type", + "X-Requested-With") + ) + + //this directive adds access control headers to normal responses + private def addAccessControlHeaders: Directive0 = { + respondWithHeaders(corsResponseHeaders) + } + + //this handles preflight OPTIONS requests. + private def preflightRequestHandler: Route = options { + complete( + HttpResponse(StatusCodes.OK).withHeaders( + `Access-Control-Allow-Methods`(OPTIONS, POST, PUT, GET, DELETE))) + } + + // Wrap the Route with this method to enable adding of CORS headers + def corsHandler(r: Route): Route = addAccessControlHeaders { + preflightRequestHandler ~ r + } + + // Helper method to add CORS headers to HttpResponse + // preventing duplication of CORS headers across code + def addCORSHeaders(response: HttpResponse): HttpResponse = + response.withHeaders(corsResponseHeaders) + +} diff --git a/app/server-routes/src/main/scala/org/bitcoins/server/routes/Server.scala b/app/server-routes/src/main/scala/org/bitcoins/server/routes/Server.scala index c737014340..1ea8976d89 100644 --- a/app/server-routes/src/main/scala/org/bitcoins/server/routes/Server.scala +++ b/app/server-routes/src/main/scala/org/bitcoins/server/routes/Server.scala @@ -18,7 +18,8 @@ case class Server( handlers: Seq[ServerRoute], rpcbindOpt: Option[String], rpcport: Int)(implicit system: ActorSystem) - extends HttpLogger { + extends HttpLogger + with CORSHandler { import system.dispatcher @@ -54,7 +55,7 @@ case class Server( handleRejections(rejectionHandler) { handleExceptions(exceptionHandler) { - route + corsHandler(route) } } }