181 lines
4.3 KiB
TypeScript
181 lines
4.3 KiB
TypeScript
import { ref } from 'vue'
|
|
|
|
/**
|
|
* 공통 API 호출
|
|
*
|
|
* @param {string} method - 요청 메소드 (GET, POST 등)
|
|
* @param {string} url - API URL
|
|
* @param {object} query - 요청 쿼리 파라미터
|
|
* @param {object} headers - 요청 헤더
|
|
* @param {object} body - 요청 본문
|
|
* @param {string} key - 캐시 키
|
|
* @param {object} loading - 로딩 설정
|
|
*/
|
|
export const commonFetch = async (
|
|
method:
|
|
| 'GET'
|
|
| 'HEAD'
|
|
| 'PATCH'
|
|
| 'POST'
|
|
| 'PUT'
|
|
| 'DELETE'
|
|
| 'CONNECT'
|
|
| 'OPTIONS'
|
|
| 'TRACE' = 'GET', // Required
|
|
url: string, // Required
|
|
{
|
|
query, // Optional
|
|
headers, // Optional
|
|
body, // Optional
|
|
key, // Optional
|
|
loading = false, // Optional
|
|
}: {
|
|
query?: object | null
|
|
headers?: object | null
|
|
body?: object | null
|
|
key?: string | null
|
|
loading?: { localId?: string } | boolean
|
|
} = {}
|
|
) => {
|
|
let result = null
|
|
const currCallerId = ref('')
|
|
const currCallerDetail = ref('')
|
|
|
|
// 로딩 스토어 가져오기 (클라이언트에서만)
|
|
let loadingStore: ReturnType<typeof useLoadingStore> | null = null
|
|
if (import.meta.client) {
|
|
try {
|
|
loadingStore = useLoadingStore()
|
|
// 로딩 시작
|
|
loadingStore.setLoading(true)
|
|
if (loading && loadingStore) {
|
|
if (typeof loading === 'object' && loading.localId) {
|
|
loadingStore.startLocalLoading(loading.localId)
|
|
} else {
|
|
loadingStore.startFullLoading()
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.warn('[Warning] Loading store not available:', e)
|
|
}
|
|
}
|
|
|
|
try {
|
|
const { callerId, callerDetail } = storeToRefs(useCallerInfoStore())
|
|
currCallerId.value = `${callerId.value}`
|
|
currCallerDetail.value = `${callerDetail.value}`
|
|
} catch (e) {
|
|
// SSR: pinia store 생성 전이므로 빈 값('') 세팅
|
|
}
|
|
|
|
try {
|
|
const options: {
|
|
method:
|
|
| 'GET'
|
|
| 'HEAD'
|
|
| 'PATCH'
|
|
| 'POST'
|
|
| 'PUT'
|
|
| 'DELETE'
|
|
| 'CONNECT'
|
|
| 'OPTIONS'
|
|
| 'TRACE'
|
|
headers: Record<string, string>
|
|
query?: object
|
|
body?: object
|
|
key?: string
|
|
} = {
|
|
method,
|
|
headers: {
|
|
'Content-Type': 'application/json;charset=UTF-8',
|
|
},
|
|
}
|
|
|
|
if (query) {
|
|
options.query = query
|
|
}
|
|
// 플랫폼 환경 API 호출 시 Caller-Id, Caller-Detail 헤더 추가
|
|
if (url.includes('.onstove.com') || url.includes('.gate8.com')) {
|
|
const callerInfo = {
|
|
'Caller-Id': `${currCallerId.value}`,
|
|
'Caller-Detail': `${currCallerDetail.value}`,
|
|
}
|
|
options.headers = { ...options.headers, ...callerInfo }
|
|
}
|
|
if (headers) {
|
|
options.headers = { ...options.headers, ...headers }
|
|
}
|
|
if (body) {
|
|
options.body = body
|
|
}
|
|
if (key) {
|
|
options.key = key
|
|
}
|
|
|
|
result = await $fetch(url, options)
|
|
} catch (e: unknown) {
|
|
console.error('[Exception] apiUtil.commonFetch: ', e)
|
|
const error = e as {
|
|
data?: unknown
|
|
statusCode?: number
|
|
statusMessage?: string
|
|
}
|
|
result = error.data || {
|
|
code: error.statusCode,
|
|
message: error.statusMessage,
|
|
}
|
|
} finally {
|
|
// 로딩 종료
|
|
if (loadingStore) {
|
|
loadingStore.setLoading(false)
|
|
if (loading) {
|
|
if (typeof loading === 'object' && loading.localId) {
|
|
loadingStore.stopLocalLoading(loading.localId)
|
|
} else {
|
|
loadingStore.stopFullLoading()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* 사용자 IP 조회
|
|
*
|
|
* @param {object} request - 요청 객체
|
|
*/
|
|
export const getTrueClientIp = (request: {
|
|
headers: Record<string, string>
|
|
socket: { remoteAddress?: string }
|
|
}) => {
|
|
const requestHeaders = request.headers
|
|
const targetHeaders = [
|
|
'True-Client-IP',
|
|
'X-Real-IP',
|
|
'X-Forwarded-For',
|
|
'Proxy-Client-IP',
|
|
'WL-Proxy-Client-IP',
|
|
'HTTP_CLIENT_IP',
|
|
'HTTP_X_FORWARDED_FOR',
|
|
]
|
|
for (const targetHeader of targetHeaders) {
|
|
let ip =
|
|
requestHeaders[targetHeader] || requestHeaders[targetHeader.toLowerCase()]
|
|
if (ip !== undefined && ip != null && ip !== '') {
|
|
if (ip.includes(',')) {
|
|
ip = ip.split(',')[0]
|
|
}
|
|
return ip
|
|
}
|
|
}
|
|
if (
|
|
request.socket.remoteAddress !== undefined &&
|
|
request.socket.remoteAddress != null &&
|
|
request.socket.remoteAddress !== ''
|
|
) {
|
|
return request.socket.remoteAddress
|
|
}
|
|
return ''
|
|
}
|