Skip to content

Commit

Permalink
Feature/fix cors error when session expired (#801)
Browse files Browse the repository at this point in the history
* Fix CORs error when the session expired

---------

Co-authored-by: khanhtranduy <[email protected]>
  • Loading branch information
khanhtrand and khanhtranduy authored Jul 25, 2024
1 parent f5a2c14 commit 9185f0a
Show file tree
Hide file tree
Showing 27 changed files with 308 additions and 394 deletions.
9 changes: 5 additions & 4 deletions backoffice-bff/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,14 @@ spring:
gateway:
routes:
- id: api
uri: http://product
uri: http://nginx
predicates:
- Path=/api/product/**
- Path=/api/**
filters:
- RewritePath=/api/(?<segment>.*), /$\{segment}
- DedupeResponseHeader=Origin Access-Control-Request-Method Access-Control-Request-Headers
- TokenRelay=
- StripPrefix=1
- id: nextjs
uri: http://localhost:3000
uri: http://backoffice-nextjs:3000
predicates:
- Path=/**
6 changes: 4 additions & 2 deletions backoffice/common/components/AuthenticationInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import Link from 'next/link';
import React, { useEffect, useState } from 'react';
import apiClientService from '@commonServices/ApiClientService';

const baseUrl = '/authentication/user';

export default function AuthenticationInfo() {
type AuthenticatedUser = {
Expand All @@ -9,8 +12,7 @@ export default function AuthenticationInfo() {
const [authenticatedUser, setAuthenticatedUser] = useState<AuthenticatedUser>({ username: '' });

async function getAuthenticatedUser() {
const res = await fetch(`/authentication/user`);
return await res.json();
return (await apiClientService.get(baseUrl)).json();
}

useEffect(() => {
Expand Down
54 changes: 54 additions & 0 deletions backoffice/common/services/ApiClientService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
interface RequestOptions {
method: string;
headers: {
[key: string]: string;
};
body?: string;
}

const sendRequest = async (
method: string,
endpoint: string,
data: any = null,
contentType: string | null = null
) => {
const defaultContentType = 'application/json; charset=UTF-8';
const requestOptions: RequestOptions = {
method: method.toUpperCase(),
headers: {
'Content-type': contentType ?? defaultContentType,
},
};

if (data) {
if (data instanceof FormData) {
delete requestOptions.headers['Content-type'];
}
requestOptions.body = data;
}

try {
const response = await fetch(endpoint, method === 'GET' ? undefined : requestOptions);

// Workaround to manually redirect in case of CORS error
if (response.type == 'cors' && response.redirected) {
window.location.href = response.url;
}

return response;
} catch (error) {
console.error('API call error:', error);
throw error;
}
};

const apiClientService = {
get: (endpoint: string) => sendRequest('GET', endpoint),
post: (endpoint: string, data: any, contentType: string | null = null) =>
sendRequest('POST', endpoint, data, contentType),
put: (endpoint: string, data: any, contentType: string | null = null) =>
sendRequest('PUT', endpoint, data, contentType),
delete: (endpoint: string) => sendRequest('DELETE', endpoint),
};

export default apiClientService;
35 changes: 13 additions & 22 deletions backoffice/modules/catalog/services/BrandService.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,35 @@
import { Brand } from '../models/Brand';
import apiClientService from '@commonServices/ApiClientService';

const baseUrl = '/api/product/backoffice/brands';

export async function getBrands(): Promise<Brand[]> {
const response = await fetch('/api/product/backoffice/brands');
return await response.json();
return (await apiClientService.get(baseUrl)).json();
}

export async function getPageableBrands(pageNo: number, pageSize: number) {
const url = `/api/product/backoffice/brands/paging?pageNo=${pageNo}&pageSize=${pageSize}`;
const response = await fetch(url);
return await response.json();
const url = `${baseUrl}/paging?pageNo=${pageNo}&pageSize=${pageSize}`;
return (await apiClientService.get(url)).json();
}

export async function createBrand(brand: Brand) {
const response = await fetch('/api/product/backoffice/brands', {
method: 'POST',
body: JSON.stringify(brand),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
return response;
return await apiClientService.post(baseUrl, JSON.stringify(brand));
}
export async function getBrand(id: number) {
const response = await fetch('/api/product/backoffice/brands/' + id);
return await response.json();
const url = `${baseUrl}/${id}`;
return (await apiClientService.get(url)).json();
}

export async function deleteBrand(id: number) {
const response = await fetch(`/api/product/backoffice/brands/${id}`, {
method: 'DELETE',
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.delete(url);
if (response.status === 204) return response;
else return await response.json();
}

export async function editBrand(id: number, brand: Brand) {
const response = await fetch(`/api/product/backoffice/brands/${id}`, {
method: 'PUT',
headers: { 'Content-type': 'application/json; charset=UTF-8' },
body: JSON.stringify(brand),
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.put(url, JSON.stringify(brand));
if (response.status === 204) return response;
else return await response.json();
}
33 changes: 12 additions & 21 deletions backoffice/modules/catalog/services/CategoryService.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,30 @@
import { Category } from '../models/Category';
import { ProductThumbnails } from '../models/ProductThumbnails';
import apiClientService from '@commonServices/ApiClientService';

const baseUrl = '/api/product/backoffice/categories';

export async function getCategories(): Promise<Category[]> {
const response = await fetch('/api/product/backoffice/categories');
return await response.json();
return (await apiClientService.get(baseUrl)).json();
}

export async function getCategory(id: number): Promise<Category> {
const response = await fetch('/api/product/backoffice/categories/' + id);
return await response.json();
const url = `${baseUrl}/${id}`;
return (await apiClientService.get(url)).json();
}

export async function createCategory(category: Category) {
const response = await fetch('/api/product/backoffice/categories', {
method: 'POST',
body: JSON.stringify(category),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
return response;
return await apiClientService.post(baseUrl, JSON.stringify(category));
}
export async function updateCategory(id: number, category: Category) {
const response = await fetch('/api/product/backoffice/categories/' + id, {
method: 'PUT',
body: JSON.stringify(category),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.put(url, JSON.stringify(category));
if (response.status === 204) return response;
else return await response.json();
}
export async function deleteCategory(id: number) {
const response = await fetch('/api/product/backoffice/categories/' + id, {
method: 'DELETE',
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.delete(url);
if (response.status === 204) return response;
else return await response.json();
}
Expand All @@ -42,6 +34,5 @@ export async function getProductsByCategory(
categorySlug: string
): Promise<ProductThumbnails> {
const url = `/api/product/storefront/category/${categorySlug}/products?pageNo=${pageNo}`;
const response = await fetch(url);
return await response.json();
return (await apiClientService.get(url)).json();
}
9 changes: 4 additions & 5 deletions backoffice/modules/catalog/services/MediaService.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { Media } from '../models/Media';
import apiClientService from '@commonServices/ApiClientService';

const baseUrl = '/api/media/medias';

export async function uploadMedia(image: File): Promise<Media> {
const body = new FormData();
body.append('multipartFile', image);
const response = await fetch('/api/media/medias', {
method: 'POST',
body: body,
});

const response = await apiClientService.post(baseUrl, body);
if (response.status >= 200 && response.status < 300) return await response.json();
return Promise.reject(response);
}
35 changes: 13 additions & 22 deletions backoffice/modules/catalog/services/ProductAttributeGroupService.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,40 @@
import { stringify } from 'querystring';
import { ProductAttributeGroup } from '../models/ProductAttributeGroup';
import apiClientService from '@commonServices/ApiClientService';

const baseUrl = '/api/product/backoffice/product-attribute-groups';

export async function getProductAttributeGroups(): Promise<ProductAttributeGroup[]> {
const response = await fetch('/api/product/backoffice/product-attribute-groups');
return await response.json();
return (await apiClientService.get(baseUrl)).json();
}

export async function getPageableProductAttributeGroups(pageNo: number, pageSize: number) {
const url = `/api/product/backoffice/product-attribute-groups/paging?pageNo=${pageNo}&pageSize=${pageSize}`;
const response = await fetch(url);
return await response.json();
const url = `${baseUrl}/paging?pageNo=${pageNo}&pageSize=${pageSize}`;
return (await apiClientService.get(url)).json();
}

export async function getProductAttributeGroup(id: number) {
const response = await fetch('/api/product/backoffice/product-attribute-groups/' + id);
return await response.json();
const url = `${baseUrl}/${id}`;
return (await apiClientService.get(url)).json();
}

export async function createProductAttributeGroup(productAttributeGroup: ProductAttributeGroup) {
const response = await fetch('/api/product/backoffice/product-attribute-groups', {
method: 'POST',
body: JSON.stringify(productAttributeGroup),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
return response;
return await apiClientService.post(baseUrl, JSON.stringify(productAttributeGroup));
}

export async function updateProductAttributeGroup(
id: number,
productAttributeGroup: ProductAttributeGroup
) {
const response = await fetch('/api/product/backoffice/product-attribute-groups/' + id, {
method: 'PUT',
body: JSON.stringify(productAttributeGroup),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.put(url, JSON.stringify(productAttributeGroup));
if (response.status === 204) return response;
else return await response.json();
}

export async function deleteProductAttributeGroup(id: number) {
const response = await fetch('/api/product/backoffice/product-attribute-groups/' + id, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.delete(url);
if (response.status === 204) return response;
else return await response.json();
}
35 changes: 13 additions & 22 deletions backoffice/modules/catalog/services/ProductAttributeService.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,40 @@
import { ProductAttribute } from '../models/ProductAttribute';
import apiClientService from '@commonServices/ApiClientService';

const baseUrl = '/api/product/backoffice/product-attribute';

interface ProductAttributeId {
name: string;
productAttributeGroupId: string;
}
export async function getProductAttributes(): Promise<ProductAttribute[]> {
const response = await fetch('/api/product/backoffice/product-attribute');
return await response.json();
return (await apiClientService.get(baseUrl)).json();
}

export async function getPageableProductAttributes(pageNo: number, pageSize: number) {
const url = `/api/product/backoffice/product-attribute/paging?pageNo=${pageNo}&pageSize=${pageSize}`;
const response = await fetch(url);
return await response.json();
const url = `${baseUrl}/paging?pageNo=${pageNo}&pageSize=${pageSize}`;
return (await apiClientService.get(url)).json();
}

export async function createProductAttribute(productAttributePost: ProductAttributeId) {
const response = await fetch('/api/product/backoffice/product-attribute', {
method: 'POST',
body: JSON.stringify(productAttributePost),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
return response;
return await apiClientService.post(baseUrl, JSON.stringify(productAttributePost));
}

export async function updateProductAttribute(id: number, productAttributeId: ProductAttributeId) {
const response = await fetch('/api/product/backoffice/product-attribute/' + id, {
method: 'PUT',
body: JSON.stringify(productAttributeId),
headers: { 'Content-type': 'application/json; charset=UTF-8' },
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.put(url, JSON.stringify(productAttributeId));
if (response.status === 204) return response;
else return await response.json();
}

export async function getProductAttribute(id: number): Promise<ProductAttribute> {
const response = await fetch('/api/product/backoffice/product-attribute/' + id);
return await response.json();
const url = `${baseUrl}/${id}`;
return (await apiClientService.get(url)).json();
}

export async function deleteProductAttribute(id: number) {
const response = await fetch('/api/product/backoffice/product-attribute/' + id, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
});
const url = `${baseUrl}/${id}`;
const response = await apiClientService.delete(url);
if (response.status === 204) return response;
else return await response.json();
}
Loading

0 comments on commit 9185f0a

Please sign in to comment.