Solution
The XMLHttpRequest access to 'http://localhost:8082/api/countries' from the origin 'http://localhost:4200' has been blocked by the CORS policy. The response to the preflight request is failing the access control check because there is no 'Access-Control-Allow-Origin' header present on the requested resource.
checkout.component.ts:153 GET http://localhost:8082/api/countries net::ERR_FAILED
angualrI have configured the server side using spring-boot :
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setAllowedOrigins(Arrays.asList(allowOrigin));
corsConfiguration.setAllowedHeaders(Arrays.asList("Origin", "Access-Control-Allow-Origin", "Content-Type",
"Accept", "Authorization", "Origin, Accept", "X-Requested-With",
"Access-Control-Request-Method", "Access-Control-Request-Headers"));
corsConfiguration.setExposedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization",
"Access-Control-Allow-Origin", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"));
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
where allowOrigin: http://localhost:4200
using REST API in pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
My country code:
package com.kaushik.bookstore.repository;
import com.kaushik.bookstore.entity.Country;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.web.bind.annotation.CrossOrigin;
@RepositoryRestResource
@CrossOrigin
@SecurityRequirement(name = "Bearer Authentication")
@Tag(
name = "Country",
description = "Here, GET all details of countries endpoint."
)
public interface CountryRepository extends JpaRepository<Country, Integer> {
}
Adding Rest App config:
package com.kaushik.bookstore.config;
import com.kaushik.bookstore.entity.Country;
import com.kaushik.bookstore.entity.Product;
import com.kaushik.bookstore.entity.ProductCategory;
import com.kaushik.bookstore.entity.State;
import jakarta.persistence.EntityManager;
import jakarta.persistence.metamodel.EntityType;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotationValue;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Configuration
@AllArgsConstructor
public class RestAppConfig implements RepositoryRestConfigurer {
private final EntityManager entityManager;
@Value("${allowed-origins}")
private String[] allowOrigin;
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
HttpMethod[] theUnsupportedActions = {HttpMethod.POST, HttpMethod.PUT,HttpMethod.PATCH, HttpMethod.DELETE};
disableHttpsMethods(Product.class, config, theUnsupportedActions);
disableHttpsMethods(ProductCategory.class, config, theUnsupportedActions);
disableHttpsMethods(Country.class, config, theUnsupportedActions);
disableHttpsMethods(State.class, config, theUnsupportedActions);
exposeIds(config);
cors.addMapping("/**")
.allowedHeaders("*")
.allowedOrigins(allowOrigin);
}
}
In Angular 15, I am using:
ngOnInit(): void {
this.formService.getCountries().subscribe((data) => {
this.countries = data;
});
}
In Form service:**http://localhost:8082/api/countries **
export class FormService {
private countriesUrl = 'http://localhost:8082/api' + '/countries';
constructor(private httpClient: HttpClient) {}
getCountries(): Observable<Country[]> {
return this.httpClient
.get<GetResponseCountries>(this.countriesUrl)
.pipe(map((response) => response.countries));
}
}
In Interceptor:
import {
HttpEvent,
HttpHandler,
HttpHeaders,
HttpInterceptor,
HttpRequest,
} from '@angular/common/http';
import { Injectable } from '@angular/core';
import { exhaustMap, Observable, take } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable()
export class AuthInterceptorService implements HttpInterceptor {
constructor(private authService: AuthService) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return this.authService.user.pipe(
take(1),
exhaustMap((user) => {
if (!user) {
return next.handle(req);
}
let tokenStr = `Bearer ${user?.token}`;
const modifyReq = req.clone({
headers: new HttpHeaders()
.set('Authorization', tokenStr)
.set('Content-Type', 'application/json'),
});
return next.handle(modifyReq);
})
);
}
}
Resolved Issue: Implementing CORS policy correctly and configuring server-side settings resolved the CORS error.