Last active
September 26, 2023 07:35
-
-
Save brownsoo/f5fc9f19fd910da087ffcacb3bff4b21 to your computer and use it in GitHub Desktop.
토큰 갱신을 위한 Ajax 목업
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Rest { | |
static apiBaseUrl = ''; | |
static getApiHeader({withoutContentType = false} = {}) { | |
const header = {}; | |
header['reqVersion'] = 2; | |
// if (authentic) { | |
// header['Authorization'] = this.getAuthToken(); | |
// } | |
if (!withoutContentType) { | |
header['Content-Type'] = 'application/json;charset=utf-8'; | |
} | |
return header; | |
} | |
static getAuthToken() { | |
const t = getToken(); | |
if (t) { | |
return 'Bearer ' + t; | |
} | |
return ''; | |
} | |
// document 로드시 한번만 수행되도록 함. | |
static isAddedAuthFilter = false; | |
static maxExpiredAuthorizationRetries = 2; | |
// https://api.jquery.com/jquery.ajaxprefilter/ | |
static makeAuthFilter() { | |
if (this.isAddedAuthFilter) return; | |
this.isAddedAuthFilter = true; | |
$.ajaxPrefilter(function (options, originalOptions, jqXHR) { | |
// 무한 반복 방지 | |
originalOptions._retry = isNaN(originalOptions._retry) | |
? Rest.maxExpiredAuthorizationRetries | |
: originalOptions._retry - 1; | |
console.log('originalOptions._retry=' + originalOptions._retry | |
+ ' originalOptions.isAuthentic=' + originalOptions.isAuthentic); | |
if (originalOptions.isAuthentic) { | |
jqXHR.setRequestHeader('Authorization', Rest.getAuthToken()); | |
} | |
// 본래 오류 콜백 저장 | |
if (originalOptions.error) { | |
originalOptions._error = originalOptions.error; | |
} | |
// 현재 오류 콜백 오버라이드 | |
options.error = $.noop(); | |
// 모든 재요청이 완료되면, 결과를 전송하도록 deferred object 생성 | |
const df = $.Deferred(); | |
jqXHR.done(df.resolve); | |
// 요청 실패 처리 | |
jqXHR.fail(async function () { | |
const args = Array.prototype.slice.call(arguments); | |
if (jqXHR.status === 401 && originalOptions._retry > 0) { | |
try { | |
// 토큰 갱신 요청 | |
await Rest.refreshToken(); | |
// 갱신 성공 후 재시도 | |
$.ajax(originalOptions).then(df.resolve, df.reject); | |
} catch (error) { | |
if (originalOptions._retry > 0) { | |
// 갱신 요청 실패 후 재시도 | |
$.ajax(originalOptions).then(df.resolve, df.reject); | |
} else { | |
df.reject(error); | |
} | |
} | |
} else { | |
// 본래 오류 콜백 추가 | |
if (originalOptions._error) { | |
df.fail(originalOptions._error); | |
} | |
df.rejectWith(jqXHR, args); | |
} | |
return df.promise(jqXHR); | |
}); | |
}); | |
} | |
/** | |
* 토큰 시간이 유효한지 체크 | |
* @returns {boolean} | |
*/ | |
static validateTokenExp() { | |
const token = getToken(); | |
const tokenExp = getCookie('tokenExp'); | |
if (token && tokenExp) { | |
const expireDate = new Date(tokenExp * 1000); | |
const now = new Date(); | |
return expireDate > now; | |
} | |
return true; | |
} | |
static correctUrl(url) { | |
if (!url || typeof url !== 'string') { | |
throw new Error('url 이 이상해!!'); | |
} | |
if (url.indexOf('http') < 0) { | |
if (url[0] !== '/') { | |
url = '/' + url; | |
} | |
return this.apiBaseUrl + url; | |
} | |
return url; | |
} | |
static refreshToken() { | |
const df = $.Deferred(); | |
let headers = this.getApiHeader(); | |
headers['Authorization'] = getRefreshToken(); | |
$.ajax({ | |
headers: headers, | |
method: 'GET', | |
url: this.correctUrl('/auth/refresh'), | |
cache: false, | |
}).done(function onSuccessRefreshToken(res) { | |
console.log(res); | |
if (!res.success) { | |
df.reject(new TokenRefreshError()); | |
} else { | |
const {accessToken, refreshToken} = res.data.tokens; | |
setToken(accessToken, refreshToken); | |
df.resolve(accessToken); | |
} | |
}).fail(function onFailRefreshToken(jqXHR, textStatus, errorThrown) { | |
console.log([jqXHR, textStatus, errorThrown]); | |
df.reject(new TokenRefreshError()); | |
}); | |
return df.promise(); | |
} | |
static createRequest(options) { | |
this.makeAuthFilter(); | |
return $.ajax(options).then(function (res) { | |
if (!res.success) { | |
throw KfError.createResponseError(res, options.url); | |
} | |
return res; | |
}).catch(function (jqXHR, textStatus, errorThrown) { | |
throw KfError.convertKfError(jqXHR, options.url); | |
}); | |
} | |
static get(url, data = undefined, authentic = true) { | |
const options = { | |
url: this.correctUrl(url), | |
headers: this.getApiHeader(), | |
method: 'GET', | |
data: data, | |
cache: false, | |
isAuthentic: authentic, | |
}; | |
return this.createRequest(options); | |
} | |
static put(url, data = undefined, authentic = true) { | |
const options = { | |
url: this.correctUrl(url), | |
headers: this.getApiHeader(), | |
method: 'PUT', | |
cache: false, | |
isAuthentic: authentic, | |
}; | |
if (data) { | |
options.data = JSON.stringify(data); | |
} | |
return this.createRequest(options); | |
} | |
static post(url, data = undefined, authentic = true) { | |
const options = { | |
url: this.correctUrl(url), | |
headers: this.getApiHeader(), | |
method: 'POST', | |
cache: false, | |
isAuthentic: authentic, | |
}; | |
if (data) { | |
options.data = JSON.stringify(data); | |
} | |
return this.createRequest(options); | |
} | |
static delete(url, data = undefined, authentic = true) { | |
const options = { | |
url: this.correctUrl(url), | |
headers: this.getApiHeader(), | |
method: 'DELETE', | |
cache: false, | |
isAuthentic: authentic, | |
}; | |
if (data) { | |
options.data = JSON.stringify(data); | |
} | |
return this.createRequest(options); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment