3

I try to access my REST API that I built using Finatra via AJAX calls. Unfortunately, I get the following error:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I have read about enabling CORS, but I could not find out how to do this in Finatra 2.1.6. I have seen that there is a policy that could be enabled and is very permissive, but I somehow do not manage to get it running. In my code I wrote:

override def configureHttp(router: HttpRouter) {
  router
    .filter(new HttpFilter(Cors.UnsafePermissivePolicy))
    .add(controller)
}

How can I set the headers properly to allow CORS in Finatra?

Evhz
  • 8,852
  • 9
  • 51
  • 69
navige
  • 2,447
  • 3
  • 27
  • 53
  • Have you tried [```CorsFilter```](https://github.com/twitter/finagle/blob/develop/finagle-http/src/main/scala/com/twitter/finagle/http/filter/Cors.scala#L236)? – Taylor Leese Jun 17 '16 at 05:33

2 Answers2

4

Apart from the CorsFilter, you need to add a controller to manage all the preflighted OPTIONS requests(please reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests), something like this:

class CorsController extends Controller {
   options("/api/:*") {
     _: Request => response.ok
   }
}

if not the preflighted requests will not be handled.

Jiji TANG
  • 91
  • 3
1

It is possible to add, general application filters, per controller filters or even action filters. Have a look at this filters section in finatra.

Its possible to go with a per-controller filter approach to solve the Cors issue. In the Server.scala file it's defined a filter:

import com.twitter.finagle.{Filter, Service, SimpleFilter}

class CorsFilter extends SimpleFilter[Request, Response] { 
    override def apply(request: Request, service: Service[Request, Response]): Future[Response] = {

        service(request).map {
            response => response.headerMap
              .add("access-control-allow-origin", "*")
              .add("access-control-allow-headers", "accept, content-type")
              .add("access-control-allow-methods", "GET,HEAD,POST,DELETE,OPTIONS,PUT,PATCH")

            response
        }
}

then, in the section where you define your server, register the controllers and attach to it the filter you just created:

object ServerMain extends Server

class Server extends HttpServer {

  override val name = "com.example.server"

  override def configureHttp(router: HttpRouter) {
    router          
      .filter[CommonFilters]
      .filter[LoggingMDCFilter[Request, Response]]
      .filter[TraceIdMDCFilter[Request, Response]]          
      .add[CorsFilter, MainController] // see the CorsFilter here    
  }
}

I hope it helps.

Evhz
  • 8,852
  • 9
  • 51
  • 69