Play Framework and CORS with Angular2 Client(Cross Origin Resource Sharing)
Although Play framework allows us to write complete web application including UI. But we can just keep our REST based HTTP service in Play Framework and access them from any other application hosted on another server. But as soon as you do it, you start getting complaints about CORS issues. For our safety, we are not allowed to request the service from a web request started on another web server. In this post, we are going to see how we can enable CORS support in our Play framework based service.
You might first download Activator. It makes it easier to start with scala application by doing the necessary scaffolding to get you started. Please download it from the following if you don’t already have it. I am sure you wouldn’t regret.
It is downloaded as a zip package. We can extract it into a folder:
Running it for the first time can bring any required dependencies to run it.
Let’s first create a Play framework service using Activator. Let’s name it as Echo Service. You guessed it right, it would just echo the data sent to it. It accepts data with a Message field (string). It responds with the contents of the field as part of its web response.
Debugging the Service
Let’s now add the debug configuration for play framework based service. Here we are selecting Play from debug configuration to be used for our service.
We are running it on port 9000. It is the default port.
Let’s first add EchoController. It just has an action. The action accepts single parameter of type string. It just returns the message back in the form of Ok response.
Now we can update routes so that play framework can route the requests to our controller. We have commented all routes and just added a route for echo action for EchoController.
Let’s now hit the service using PostMan. Here we are passing the message as part of the query parameter, as expected by the EchoController. As expected, we are getting the same message echoed by the service.
Now let’s create a client to use our Echo Service. Since this would be hosted on a separate host, we can create a scenario of Cross Origin request for the service and discuss how we can resolve the issue. Here we are creating an Angular2 client. We are naming the Client as EchoServiceClient, which is certainly very intuitive 🙂
Let’s start by adding EchoRequestService in services folder in app.component. The service just has a method which accepts a message as an argument. It sends an Http request to our Echo Service running on port 9000. Angular2’s Http module returns an Observable<Response>. Here we are just extracting the response’s text from and returning Observable<String> from the method. The class is decorated as Injectable so that we could inject it to app.component.
Let’s turn our attention to app.component.ts. Since we just need EchoRequestService in this component, we are adding it to the providers section in the component’s decorator. We are also injecting the service in the component’s constructor. The component has two properties inputMessage: String and echoedMessage: Observable
Now we just need to update the template to use the properties from the component. We are binding the inputMessage property to a text box. This is a two way binding. We are also using echoedMessage property. We are using async filter since this is an Observable.
Since we already have the play framework service running, we can just ng serve the angular2 project. This runs as localhost:4200 by default. We enter some message to the text box and click the button. To our surprise, we get the following error based response from play service.
This is actually a common problem when we request another service from another web application hosted separately. Here we need to build some kind of relationship between the two applications. This requires play framework service to recognize our Angular application running as localhost:4200 as one of the allowed origins. But this requires a bit of plumbing.
First we need to add filters as dependencies to build.sbt. This changes the build.sbt as follows:
This would add necessarily dependencies to our service by adding the necessary library references. This includes availability of CORSFilter. We need to just update Filters to use this filter. Now the request pipeline would use CORSFilter as one of the filter before serving the resource as specified by the route.
But this is not enough. We still need to add localhost:4200 as one of the allowed origins. Actually CorsFilter configuration is already added to application.conf. It’s just commented out. We can just uncomment the following section and add localhost:4200. In case we need to allow all origins, we can just assign null to it.
Now we can run the service again. We notice that the play framework service now honors the request from Angular application running on localhost:4200 and echoes the response as expected.