0

My project uses spring at the back-end and angular2 at the front-end. I have a json file under webapp folder of spring project. And I am trying to access it from angular.

I am able to access the file if I just type "http://localhost:8080/project1/test.json"

But if I use the same link from angular, I am getting an error message saying "no access control allow origin header"

My angular code : 1. Function getJson() defined in service.ts:

 getJson(){
    return this.http.get('http://localhost:8080/project1/test.json')
    .map((response:Response) => response.json());
}
  1. Calling getJson():

    results=[];

    this._manoService.getJson().subscribe(resJsonData => this.results = resJsonData);

I created proxy.conf.json and added the following lines:

{
 "/project1": {
 "target": "http://localhost:8080",
 "secure": false
   } 
}

And also added "start": "ng serve --proxy-config proxy.conf.json", to package.json

Still I am getting the same issue. Am I doing anything wrong?

Mukund S
  • 95
  • 2
  • 2
  • 8
  • What does your URL look like when you're calling this page? – Chester Aug 15 '17 at 18:36
  • @Chester may I know which URL are you asking about? – Mukund S Aug 15 '17 at 18:43
  • Use jsonp for the call as described in this link below : https://stackoverflow.com/questions/36289495/how-to-make-a-simple-jsonp-asynchronous-request-in-angular-2/36289568#36289568 – soulzcore Aug 15 '17 at 18:45
  • @Mukund The URL you're calling the webpage from. Does it start with `http://localhost:8080` also? Or does it start with `file:///` – Chester Aug 15 '17 at 18:45
  • @Chester it is "http://localhost:3000" – Mukund S Aug 15 '17 at 18:47
  • Ah, that is the problem. You're calling from two different servers (`localhost:8008` and `localhost:3000`). See the answer below from Hendrick. – Chester Aug 15 '17 at 18:49
  • Since this is tagged with angular and angular (front-end) has nothing to do with CORS issues. I'm flagging this as duplicate. Your question should've been more like how can I enable CORS in a Spring project which @alayor has already marked. – eko Aug 16 '17 at 04:40

2 Answers2

0

For security reasons, browsers enforce a same origin policy. Your angular page is on an origin other than localhost:8080 (most likely localhost:3000). So the browser is disallowing access.

The SOP is a very important concept of the web. For example you may be logged in to your bank account and then open another website. The SOP prevents that website from accessing your bank account.

There are several ways to grant cross origin access.

By far the easiest way, is to put everything onto the same origin. That is provide the Angular application on the same domain and port as the service for production. For development, you can configure ng serve to act as a proxy server. Thus you will make your service request to http://localhost:3000/project1/test.json and let ng service forward it to localhost:8080. This is explained in detail in Angular proxy documentation.

If you need cross origin request even in production, Spring makes it relatively easy to allow that: You need toannotate your service methods with @CrossOrigin as explained in the Spring REST tutorial. In this case authentication via cookie will not work any longer. In case you need authentication, you should look into oauth. Adding the @CrossOrigin annotication to your service method, will make Spring-REST add the Access-Control-Allow-Origin http-header.

Another alternative to using proper CORS is to use jsonp, but this is a hack that should be avoided nowadays. JSONP exploits use of the fact, that you can include a <script> tag to any origin and the provided javascript is downloaded and execute. So the idea behind JSONP is that you define a callback function and the server will generate and return JavaScript code that invokes this function with the actual data as parameter.

Hendrik Brummermann
  • 8,242
  • 3
  • 31
  • 55
  • I tried adding following code in prof.conf.json { "/project1": { "target": "http://localhost:8080", "secure": false } still the same issue. Am I am doing anything wrong? } – Mukund S Aug 15 '17 at 20:19
  • Did you change the `this.http.get` code line to point to localhost:3000? – Hendrik Brummermann Aug 15 '17 at 21:26
0

Let's say that the service is implemented by a Spring @RestController and you need to consume it throught a web site that is outside of the server where the rest service is running. In that scenario just add a @CrossOrigin annotation to the handler method.

For example (in this example the @CrossOrigin is enable only to the addSite handler method.

@RestController
public class SiteController {

    @Autowired
    private SiteServiceImpl siteService;

    @CrossOrigin(origins = "*")
    @RequestMapping(method = RequestMethod.POST, value = "/api/sites")
    public void addSite(@RequestBody Site site){
        siteService.addSite(site);
    }

But also you can enable @CrossOrigin to the whole controller enabling the @CrossOrigin at the @RestController level.

For example:

@RestController
@CrossOrigin(origins = "*")
public class SiteController {

    @Autowired
    private SiteServiceImpl siteService;


    @RequestMapping(method = RequestMethod.POST, value = "/api/sites")
    public void addSite(@RequestBody Site site){
        siteService.addSite(site);
    }

@CrossOrigin(origins = "*") annotation allows to all the resources that are outside of the rest service to consume it, in the case that the service is only enabled to be consumed for resources that comes from one specific origin then just change the origins value to the server name where the resources resides, for example @CrossOrigin(origins = "http://myothersite.com")

There is more related information at the Spring site: cors-support-in-spring-framework

Daniel C.
  • 5,418
  • 3
  • 23
  • 26