2

I am writing a application in angular with java. Here I am writing a get method in angular, it is going to front end and the back end java service is returning a list of object. But the angular get method is directly going to error part.

Java service:-

    @GetMapping(value = "/getStatusMails")
    public ResponseEntity<Object> getStatusMails() {
        List<Dto> status= sercice.getStatusMails(123);
        return new ResponseEntity<Object>(status, HttpStatus.OK);
    }

angular get method: -

    this.httpClient.get<any>('http://IP:8090/getStatusMails').subscribe(
    data => this.elements = data,
    error => console.error('There was an error!', error))

I have tested with postman, it is getting the proper list of objects.

My console error: -

Access to XMLHttpRequest at 'http://IP:8090/getStatusMails' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
zone-evergreen.js:2845 GET http://IP:8090/getStatusMails net::ERR_FAILED
core.js:6241 ERROR HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "http://IP:8090/getStatusMails", ok: false, …}

If I write my code like below

const url = "http://IP:8090/getStatusMails"; // site that doesn’t send Access-Control-*
    fetch(url)
    .then(response => response.text())
    .then(contents => console.log(contents))
    .catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
}

In my console I am getting the console like Can’t access http://IP:8090/getStatusMails response. Blocked by browser? When I click on my url in the log, I am able to see the output in another window.

enter image description here

enter image description here

Gen
  • 2,400
  • 4
  • 24
  • 46

3 Answers3

3

Http error code 0 is caused by CORS: your Angular application is hosted on a different host than your Java application and XHR requests are forbidden.

To solve this, you can either use a reverse proxy (recommended) or add Access Control http headers to your backend.

Using a reverse proxy

During development

Create a proxy.json file in the same folder than your package.json:

{
    "/getStatusMails": {
        "target": "http://IP:8090",
        "secure": false,
        "changeOrigin": true
    }
}

And start your Angular dev server with --proxy-config proxy.json :

ng serve --proxy-config proxy.json

Now instead of sending a request to http://IP:8090/getStatusMails, you can simply request /getStatusMails.

If you have multiple services, you can define a common prefix for them (like /api or /rest):

  • /api/getStatusMails
  • /api/getUsers

(Although I would recommend following REST naming conventions).

And then configure the proxy using the prefix:

{
    "/api": {
        "target": "http://IP:8090",
        "secure": false,
        "changeOrigin": true
    }
}

In production, you either have to deploy everything on the same Java server or you have to configure a reverse proxy in your web server (Apache Httpd or Nginx).

Apache Httpd

You have to enable mod_proxy and then you can configure it with ProxyPass and ProxyPassReverse:

ProxyPass         "/getStatusMails" "http://IP:8090/"
ProxyPassReverse  "/getStatusMails" "http://IP:8090/"

You can find more information on Apache Http documentation.

Nginx

Using proxy_path property:

location /getStatusMails {
    proxy_pass http://IP:8090/;
}

You can find more information on Nginx documentation.

Using Access Control http headers

In this configuration, user's web browser will send an OPTION request before sending the real XHR request.

Your Java application have to send Access-Control-Allow-Origin and Access-Control-Allow-Methods headers to allow cross origin requests.

For example, during development you could send:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST

To allow GET and POST requests from any URLs.

In production, you should never use * and always specify the real URL of your frontend.

Since you seems to be using Spring, you can simply annotate your method with @CrossOrigin to send these headers. You can find more information about this in  Spring documentation.

Raphaël
  • 3,646
  • 27
  • 28
  • Do I need to do this process for each and every get method? if so is there any alternate for this? – Gen Aug 04 '20 at 01:54
  • 1
    There is an other way, you can use a prefix like /api or /rest for your services and map the reverse proxy to the prefix – Raphaël Aug 04 '20 at 03:48
1

This is a CORS error.

This occurs when your client is running on a different server than that of backend.

so why this doesn't occur in Postman?

  • postman is for development purpose and doesn't have any built-in checks for the origin

why does this happen in the browser?

  • browsers checks for origin to prevent CSRF attacks.

The solution to your problem is to add your client's URL in 'Allow-Acess-Control_origin' at your server-side. check this on how to do that.

you can either set 'Allow-Acess-Control_origin'to * , (accept all connections) or you can specify the client URL's

Amod Shinde
  • 144
  • 9
0

Adding @CrossOrigin annotation to your controller in your Java service should fix your issue.

@CrossOrigin
@GetMapping(value = "/getStatusMails")
    public ResponseEntity<Object> getStatusMails() {
        List<Dto> status= sercice.getStatusMails(123);
        return new ResponseEntity<Object>(status, HttpStatus.OK);
    }