233 lines
6.8 KiB
JavaScript
233 lines
6.8 KiB
JavaScript
import axios, { Axios } from 'axios'
|
|
import { v4 as uuidv4 } from 'uuid'
|
|
|
|
const AxiosType = {
|
|
INTERNAL: 'Internal',
|
|
EXTERNAL: 'External',
|
|
}
|
|
|
|
// WRITE 요청 식별용. 호출자가 option.headers['X-Idempotency-Key'] 를 직접 지정하면 그대로 사용.
|
|
const WRITE_METHODS = ['post', 'put', 'patch']
|
|
|
|
/**
|
|
* axios 인스턴스 생성 후 반환
|
|
* @param {String} lang
|
|
* @returns http request instance - get, post, put, patch, delete (promise 접수사가 붙은 함수는 promise 반환)
|
|
*/
|
|
export function useAxios(lang = '') {
|
|
const getInstances = (url) => {
|
|
/**
|
|
* url이 http로 시작하면 외부 서버로 판단
|
|
*/
|
|
let type = AxiosType.INTERNAL
|
|
url.startsWith('http') ? (type = AxiosType.EXTERNAL) : ''
|
|
|
|
/**
|
|
* 내부 서버로 요청 시 lang 헤더 추가
|
|
*/
|
|
let headerValue = {
|
|
Accept: 'application/json',
|
|
}
|
|
url.startsWith('https') ? '' : (headerValue['lang'] = lang)
|
|
|
|
const instance = axios.create({
|
|
baseURL: type === AxiosType.INTERNAL ? process.env.NEXT_PUBLIC_API_SERVER_PATH : '',
|
|
headers: headerValue,
|
|
})
|
|
|
|
// WRITE 메서드에 X-Idempotency-Key 자동 부착 (override 가능)
|
|
instance.interceptors.request.use((config) => {
|
|
const method = (config.method || '').toLowerCase()
|
|
if (WRITE_METHODS.includes(method)) {
|
|
config.headers = config.headers || {}
|
|
if (!config.headers['X-Idempotency-Key']) {
|
|
config.headers['X-Idempotency-Key'] = uuidv4()
|
|
}
|
|
}
|
|
return config
|
|
})
|
|
|
|
return instance
|
|
}
|
|
|
|
// request 추가 로직
|
|
axios.interceptors.request.use((config) => {
|
|
return config
|
|
})
|
|
|
|
// response 추가 로직
|
|
axios.interceptors.response.use(
|
|
(response) => {
|
|
// 500 에러 로깅
|
|
if (response.status === 500) {
|
|
console.error('🚨 500 Error Response:', {
|
|
url: response.config.url,
|
|
method: response.config.method,
|
|
status: response.status,
|
|
statusText: response.statusText,
|
|
timestamp: new Date().toISOString(),
|
|
requestData: response.config.data,
|
|
responseData: response.data
|
|
})
|
|
}
|
|
return response
|
|
},
|
|
(error) => {
|
|
// 500 에러 및 기타 에러 로깅
|
|
if (error.response?.status === 500) {
|
|
console.error('🚨 500 Error Caught:', {
|
|
url: error.config?.url,
|
|
method: error.config?.method,
|
|
status: error.response?.status,
|
|
statusText: error.response?.statusText,
|
|
timestamp: new Date().toISOString(),
|
|
requestData: error.config?.data,
|
|
errorMessage: error.message,
|
|
errorStack: error.stack
|
|
})
|
|
} else {
|
|
console.error('🚨 API Error:', {
|
|
url: error.config?.url,
|
|
method: error.config?.method,
|
|
status: error.response?.status,
|
|
statusText: error.response?.statusText,
|
|
timestamp: new Date().toISOString(),
|
|
errorMessage: error.message
|
|
})
|
|
}
|
|
return Promise.reject(error)
|
|
}
|
|
)
|
|
|
|
const get = async ({ url, option = {} }) => {
|
|
return await getInstances(url)
|
|
.get(url, option)
|
|
.then((res) => res.data)
|
|
.catch((error) => {
|
|
// 500 에러는 재시도되므로 로깅을 줄임
|
|
const status = error?.response?.status
|
|
if (status === 500) {
|
|
console.warn('🔄 Server Error (500): Will retry...', url)
|
|
} else {
|
|
console.error('🚨 GET Error:', {
|
|
url,
|
|
method: 'GET',
|
|
timestamp: new Date().toISOString(),
|
|
errorMessage: error.message,
|
|
status: error.response?.status,
|
|
statusText: error.response?.statusText,
|
|
config: error.config
|
|
})
|
|
}
|
|
throw error
|
|
})
|
|
}
|
|
|
|
const promiseGet = async ({ url, option = {} }) => {
|
|
return await getInstances(url).get(url, option)
|
|
}
|
|
|
|
const post = async ({ url, data, option = {} }) => {
|
|
return await getInstances(url)
|
|
.post(url, data, option)
|
|
.then((res) => res.data)
|
|
.catch((error) => {
|
|
console.error('🚨 POST Error:', {
|
|
url,
|
|
method: 'POST',
|
|
timestamp: new Date().toISOString(),
|
|
errorMessage: error.message,
|
|
status: error.response?.status,
|
|
statusText: error.response?.statusText,
|
|
requestData: data,
|
|
config: error.config
|
|
})
|
|
throw error
|
|
})
|
|
}
|
|
|
|
const promisePost = async ({ url, data, option = {} }) => {
|
|
return await getInstances(url).post(url, data, option)
|
|
}
|
|
|
|
const put = async ({ url, data, option = {} }) => {
|
|
return await getInstances(url)
|
|
.put(url, data, option)
|
|
.then((res) => res.data)
|
|
.catch((error) => {
|
|
console.error('🚨 PUT Error:', {
|
|
url,
|
|
method: 'PUT',
|
|
timestamp: new Date().toISOString(),
|
|
errorMessage: error.message,
|
|
status: error.response?.status,
|
|
statusText: error.response?.statusText,
|
|
requestData: data,
|
|
config: error.config
|
|
})
|
|
throw error
|
|
})
|
|
}
|
|
|
|
const promisePut = async ({ url, data, option = {} }) => {
|
|
return await getInstances(url).put(url, data, option)
|
|
}
|
|
|
|
const patch = async ({ url, data, option = {} }) => {
|
|
return await getInstances(url)
|
|
.patch(url, data, option)
|
|
.then((res) => res.data)
|
|
.catch((error) => {
|
|
console.error('🚨 PATCH Error:', {
|
|
url,
|
|
method: 'PATCH',
|
|
timestamp: new Date().toISOString(),
|
|
errorMessage: error.message,
|
|
status: error.response?.status,
|
|
statusText: error.response?.statusText,
|
|
requestData: data,
|
|
config: error.config
|
|
})
|
|
throw error
|
|
})
|
|
}
|
|
|
|
const promisePatch = async ({ url, data, option = {} }) => {
|
|
return await getInstances(url).patch(url, data, option)
|
|
}
|
|
|
|
const del = async ({ url, option = {} }) => {
|
|
return await getInstances(url)
|
|
.delete(url, option)
|
|
.then((res) => res.data)
|
|
.catch((error) => {
|
|
console.error('🚨 DELETE Error:', {
|
|
url,
|
|
method: 'DELETE',
|
|
timestamp: new Date().toISOString(),
|
|
errorMessage: error.message,
|
|
status: error.response?.status,
|
|
statusText: error.response?.statusText,
|
|
config: error.config
|
|
})
|
|
throw error
|
|
})
|
|
}
|
|
|
|
const promiseDel = async ({ url, option = {} }) => {
|
|
return await getInstances(url).delete(url, option)
|
|
}
|
|
|
|
const getFetcher = async (url) => {
|
|
const res = await get({ url })
|
|
return res
|
|
}
|
|
|
|
const postFetcher = async (url, arg, option = {}) => {
|
|
const res = await post({ url, data: arg, option })
|
|
return res
|
|
}
|
|
|
|
return { get, promiseGet, post, promisePost, put, promisePut, patch, promisePatch, del, promiseDel, getFetcher, postFetcher }
|
|
}
|