-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Global/aos] Bearer Interceptor 구현 #110
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,88 @@ | ||
package com.avengers.nibobnebob.config | ||
|
||
|
||
import com.avengers.nibobnebob.app.DataStoreManager | ||
import com.avengers.nibobnebob.data.model.BaseState | ||
import com.avengers.nibobnebob.data.model.request.RefreshTokenRequest | ||
import com.avengers.nibobnebob.data.model.response.BaseResponse | ||
import com.avengers.nibobnebob.data.model.response.NaverLoginResponse | ||
import com.avengers.nibobnebob.data.model.runRemote | ||
import com.avengers.nibobnebob.data.remote.RefreshApi | ||
import com.avengers.nibobnebob.presentation.util.Constants | ||
import kotlinx.coroutines.flow.first | ||
import kotlinx.coroutines.runBlocking | ||
import okhttp3.Interceptor | ||
import okhttp3.OkHttpClient | ||
import okhttp3.Response | ||
import okhttp3.logging.HttpLoggingInterceptor | ||
import retrofit2.Retrofit | ||
import retrofit2.converter.gson.GsonConverterFactory | ||
import java.io.IOException | ||
import javax.inject.Inject | ||
|
||
class BearerInterceptor @Inject constructor() : Interceptor { | ||
class BearerInterceptor @Inject constructor( | ||
private val dataStoreManager: DataStoreManager | ||
) : Interceptor { | ||
|
||
@Throws(IOException::class) | ||
override fun intercept(chain: Interceptor.Chain): Response { | ||
|
||
val originalRequest = chain.request() | ||
val response = chain.proceed(originalRequest) | ||
|
||
// runBlocking { | ||
// 로컬에 refreshToken이 있다면 | ||
// sharedPreferences.getString(X_REFRESH_TOKEN, null)?.let { refresh -> | ||
// Log.d(TAG, refresh) | ||
// // refresh API 호출 | ||
// val result = Retrofit.Builder() | ||
// .baseUrl(BASE_DEV_URL) | ||
// .addConverterFactory(GsonConverterFactory.create()) | ||
// .build() | ||
// .create(RefreshAPI::class.java).refreshToken(refresh) | ||
// | ||
// if (result.isSuccessful) { | ||
// Log.d(TAG,"리프래시 성공") | ||
// result.body()?.let { body -> | ||
// Log.d(TAG,body.accessToken) | ||
// // refresh 성공시 로컬에 저장 | ||
// sharedPreferences.edit() | ||
// .putString(X_ACCESS_TOKEN, body.accessToken) | ||
// .putString(X_REFRESH_TOKEN, body.refreshToken) | ||
// .apply() | ||
// | ||
// isRefreshed = true | ||
// accessToken = body.accessToken | ||
// } | ||
// }else{ | ||
// val error = | ||
// Gson().fromJson(result.errorBody()?.string(), ErrorResponse::class.java) | ||
// Log.d(TAG,error.message) | ||
// } | ||
// } | ||
// } | ||
// | ||
// if (isRefreshed) { | ||
// | ||
// // 기존 API 재호출 | ||
// val newRequest = originalRequest.newBuilder() | ||
// .addHeader("Authorization", accessToken) | ||
// .build() | ||
// | ||
// return chain.proceed(newRequest) | ||
// } | ||
// 해당 특정 에러코드가 그대로 내려간다면, 세션 만료 처리 | ||
var newAccessToken: String? = null | ||
|
||
if (response.code == TOKEN_ERROR) { | ||
runBlocking { | ||
val refreshToken = dataStoreManager.getRefreshToken().first() | ||
refreshToken?.let { token -> | ||
when (val result = getNewAccessToken(token)) { | ||
is BaseState.Success -> { | ||
response.close() | ||
newAccessToken = result.data.body.accessToken | ||
newAccessToken?.let { | ||
dataStoreManager.putAccessToken(newAccessToken!!) | ||
} | ||
} | ||
|
||
else -> { | ||
dataStoreManager.deleteAccessToken() | ||
dataStoreManager.deleteRefreshToken() | ||
} | ||
} | ||
} | ||
} | ||
(newAccessToken)?.let { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사소한 컨밴션 이지만 이거 괄호 왜 썼는지? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 연산을 하려고 했는데 연산을 지우면서 같이 안 지운거같아 ㅋㅋㅋㅋㅋ 다음 커밋때 지울게요! |
||
val newRequest = originalRequest.newBuilder() | ||
.addHeader(AUTHORIZATION, "$BEARER $newAccessToken") | ||
.build() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 기존 request 가 열려있으면 에러가 나서 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 같은 파일 41 줄에 response.close() 넣어뒀어! 어디 넣어하는건지 잘 몰라서 일단 재발급 성공한 직후에 넣어뒀는데 여기로 옮기는게 나을까? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아! 못봤다ㅜㅜ 기존 위치가 좋은거 같아 |
||
return chain.proceed(newRequest) | ||
} | ||
} | ||
|
||
return response | ||
} | ||
|
||
|
||
private suspend fun getNewAccessToken(refreshToken: String?): BaseState<BaseResponse<NaverLoginResponse>> { | ||
val loggingInterceptor = HttpLoggingInterceptor() | ||
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY | ||
val okHttpClient = OkHttpClient.Builder().addInterceptor(loggingInterceptor).build() | ||
|
||
val retrofit = Retrofit.Builder() | ||
.baseUrl(Constants.BASE_URL) | ||
.addConverterFactory(GsonConverterFactory.create()) | ||
.client(okHttpClient) | ||
.build() | ||
val api = retrofit.create(RefreshApi::class.java) | ||
return runRemote { api.refreshToken(RefreshTokenRequest(refreshToken)) } | ||
Comment on lines
+72
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분에 대해서 왜 retrofit을 di를 안했지? 라는 의문이 들었는데
내가 이해한 바로는 retrofit -> okhttpclient -> bearerinterceptor -> retrofit 이렇게 순환참조가 일어나서 이렇게 선언을 했다고 생각하는데 생각하는 바가 맞는걸까?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞아!! 나도 di 로 하려고했는데 사이클이 돌아서 안되더라고.. |
||
} | ||
|
||
companion object { | ||
const val TOKEN_ERROR = 401 | ||
const val AUTHORIZATION = "Authorization" | ||
const val BEARER = "Bearer" | ||
} | ||
Comment on lines
+81
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분 util패키지 -> constants에서 관리하고 있는데 거기다가 진행하는 거는 어떨까? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. constants 에 지금 상수값이 거의 다 들어가있어서 좀 나눠서 관리하는건 어떨까 싶어. 예를들어 Constant 라고만 하면 나중에 무슨 상수값인지 모르니까 값을 불러오려면 파일에 들어가서 확인해야하는데, Error, Network, Token 뭐 이런식으로 하면 쉽게 찾을 수 있을것 같아. 장단이 있을거 같은데 얘기해보면 좋을듯! |
||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package com.avengers.nibobnebob.data.model.request | ||
|
||
data class RefreshTokenRequest( | ||
val refreshToken: String? | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
package com.avengers.nibobnebob.data.remote | ||
|
||
import com.avengers.nibobnebob.data.model.request.RefreshTokenRequest | ||
import com.avengers.nibobnebob.data.model.response.BaseResponse | ||
import com.avengers.nibobnebob.data.model.response.NaverLoginResponse | ||
import retrofit2.Response | ||
import retrofit2.http.Body | ||
import retrofit2.http.POST | ||
|
||
interface RefreshApi { | ||
|
||
@POST("토큰 갱신 url") | ||
suspend fun refreshToken(refreshToken : String) : Response<BaseResponse<NaverLoginResponse>> | ||
@POST("api/auth/refresh-token") | ||
suspend fun refreshToken(@Body refreshToken: RefreshTokenRequest) : Response<BaseResponse<NaverLoginResponse>> | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
accesstokenInterceptor 없었는데 같이 추가 👍👍👍👍