DEV Community

Cover image for CORS Proxy Angular
Jimy  Dolores
Jimy Dolores

Posted on • Updated on

CORS Proxy Angular

Cuando trabajamos consumiendo APIS, a menudo podemos toparnos con un error de CORS, puede ser un Backend Server local o alguna API publica, y a mi en lo particular cuando me tope con este problema, pues me tomo tiempo encontrar una solución, talvez a algunos se les cruzo por la cabeza cuando levantaban su server local "pero si ya habilite CORS ¿Por qué sigo con este problema?", bueno para aquellos que estén pasando por este problema, les traigo la solución.😁

En esta ocasión estoy usando angular 9, será una aplicación sencilla, y levantare un Backend Server local, bueno manos a la obra.

Nuestro servidor Backend expondrá un API Rest llamado greeting el cual usa un método GET: http://localhost:8080/apidemo/greeting y mostrara el siguiente json:

Alt Text

creamos nuestra aplicación angular:

ng new demo-proxy-angular
Enter fullscreen mode Exit fullscreen mode

una vez que que haya terminado de crear nuestro proyecto, lo abrimos con nuestro editor de código, en mi caso VSCode, y nos dirigimos a nuestro AppModule y agregamos el modulo HttpClientModule

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Enter fullscreen mode Exit fullscreen mode

dentro de la carpeta app crearemos un archivo llamado "apirest.service.ts" y dentro crearemos una función que consumirá nuestra API Rest, la llamaremos getGreeting()

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ApiRestService {
  constructor(private http: HttpClient) { }

  getGreeting(): Observable<any> {
    return this.http.get<any>('http://localhost:8080/apidemo/greeting');
  }
}

Enter fullscreen mode Exit fullscreen mode

Ahora vamos a nuestro app.component.ts para hacer uso de nuestro servicio, implementamos la interfaz OnInit

import { Component, OnInit } from '@angular/core';
import { ApiRestService } from 'src/app/apirest.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'demo-proxy-angular';
  constructor(private apiRestService: ApiRestService) { }
  ngOnInit() {
    this.apiRestService.getGreeting().subscribe(data => {
      console.log(data);
    });
  }
}

Enter fullscreen mode Exit fullscreen mode

listo!, ahora corremos nuestra aplicación:

ng s -o
Enter fullscreen mode Exit fullscreen mode

Cuando nuestra aplicación inicie se llamara al método ngOnInit el cual llamara a nuestro servicio.

Alt Text

y como verán nos arroja error de CORS 😱

Ahora viene el truco😎, en la raíz de nuestro proyecto crearemos un archivo llamado proxy.conf.json y contendrá lo siguiente:

Atributos

  • target: Se define la url de nuestro backend.
  • secure: es aplicar el uso de SSL.
  • logLevel: Para comprobar que todo funcione correctamente debemos indicar el valor en debug.

OJO con este dato muchachos!, si nuestro backend no se esta ejecutando localmente debemos de agregar el atributo:

  • changeOrigin:true

En mi caso estoy corriendo un backend local por lo que no es necesario, pero ahí tienen el dato chicos. 🤗

{
  "/apidemo/*": {
    "target": "http://localhost:8080",
    "secure": false,
    "logLevel": "debug"
  }
}

Enter fullscreen mode Exit fullscreen mode

el atributo "/apidemo/*" es el nombre que usaremos para invocar el servicio.

Ya que tenemos nuestro archivo proxy, ahora tenemos que modificar nuestro archivo angular.json, dirijanse a serve > options deberán de agregar el atributo "proxyConfig" :

...
"serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "demo-proxy-angular:build",
            "proxyConfig": "proxy.conf.json"
          },
....
Enter fullscreen mode Exit fullscreen mode

Guardan los cambios y ahora realizaremos una modificación a la manera en que llamamos nuestra api:

  getGreeting(): Observable<any> {
    // return this.http.get<any>('http://localhost:8080/apidemo/greeting');
    return this.http.get<any>('apidemo/greeting');

  }
Enter fullscreen mode Exit fullscreen mode

Fíjense que ahora solo coloco apidemo/greeting ya que nuestro proxy se encargara de reescribir la petición. 😎

Ahora modificaremos nuestro archivo "package.json" y agregaremos el siguiente comando:

 "scripts": {
   ...
    "start:proxy": "ng serve --proxy-config  proxy.conf.json  --open"
  },
Enter fullscreen mode Exit fullscreen mode

con este comando ejecutaremos nuestra aplicación con la configuración de nuestro proxy, y ahora los resultados.

Alt Text

Alt Text

Recuerden, esta configuración no funciona en producción, es para poder mitigar estos inconvenientes de CORS en el proceso de desarrollo FrontEnd.

Y eso es todo por hoy amigos, espero que esta información les ayude, aquí les dejo un repositorio en GitHub con las configuraciones que hemos visto https://github.com/jimmyhdolores/demo-proxy-angular

Si tienen alguna duda o consulta me escriben, no hay problema 🤗
Sigueme en Github https://github.com/jimyhdolores

**Actualización 14/06/2020
Aquí les dejo el vídeo donde implemento todo lo explicado, dale Like si te gusta y suscribete:
https://www.youtube.com/watch?v=CE52eOj4C_I&t=50s

Top comments (2)

Collapse
 
raimonxdev profile image
RaimonxDev • Edited

Tengo mi app en producción y tengo este problema. Cuál podría ser la solución para este caso ? El detalle es que cuando realizó la primera petición sale los cors , luego cuando recargo desaparece, eso me imagino que se debe a qué queda en caché el data.. pero como hago para evitar el error del cors, tengo mi app en domain.com y la api en api.domain.com

Collapse
 
jimyhdolores profile image
Jimy Dolores • Edited

Hola RaimonxDev, primero tendrías que verificar si tu petición se este realizando la primera vez a "api.domain.com", si es así entonces en tu Servidor BackEnd debes de habilitar CORS para el dominio que este haciendo la petición, ya que es un entorno de producción, un ejemplo en SpringBoot es:


    @CrossOrigin(origins = "domain.com")
    @GetMapping("/tuapi")
    public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) {
        System.out.println("==== in greeting ====");
        return new Greeting(counter.incrementAndGet(), String.format(template, name));
    }