11package me.proxer.library.internal.interceptor
22
33import com.squareup.moshi.JsonDataException
4+ import com.squareup.moshi.JsonReader
45import me.proxer.library.LoginTokenManager
56import me.proxer.library.ProxerException.ServerErrorType
67import me.proxer.library.util.ProxerUrls
@@ -16,8 +17,8 @@ internal class LoginTokenInterceptor(private val loginTokenManager: LoginTokenMa
1617 private const val LOGIN_TOKEN_HEADER = " proxer-api-token"
1718 private const val MAX_PEEK_BYTE_COUNT = 1_048_576L
1819
19- private val LOGIN_TOKEN_PATTERN = Regex ( " \" token \" :.*? \" (.+?) \" " , RegexOption . DOT_MATCHES_ALL )
20- private val ERROR_PATTERN = Regex ( " \" code \" :.*?( \\ d+ \b ?) " , RegexOption . DOT_MATCHES_ALL )
20+ private val OPTIONS = JsonReader . Options .of( " code " , " data " )
21+ private val TOKEN_OPTIONS = JsonReader . Options .of( " token " )
2122
2223 private val LOGIN_URL = ProxerUrls .apiBase.newBuilder()
2324 .addPathSegment(" user" )
@@ -55,36 +56,76 @@ internal class LoginTokenInterceptor(private val loginTokenManager: LoginTokenMa
5556 }
5657
5758 private fun handleResponse (response : Response ): Response {
58- val responseBody = peekResponseBody(response)
59- val url = response.request.url
59+ if (response.isSuccessful) {
60+ val (errorCode, token) = peekResponse(response)
61+
62+ synchronized(lock) {
63+ val errorType = errorCode?.let { ServerErrorType .fromErrorCode(it) }
64+
65+ if (errorType != null ) {
66+ if (errorType.isLoginError) {
67+ loginTokenManager.persist(null )
68+ }
69+ } else if (response.request.url.pathSegments == LOGIN_URL .pathSegments) {
70+ if (token != null ) {
71+ loginTokenManager.persist(token)
72+ } else {
73+ throw JsonDataException (" No token found after successful login." )
74+ }
75+ } else if (response.request.url.pathSegments == LOGOUT_URL .pathSegments) {
76+ loginTokenManager.persist(null )
77+ }
78+ }
79+ }
80+
81+ return response
82+ }
6083
61- synchronized(lock) {
62- val potentialError = ERROR_PATTERN .find(responseBody )
84+ private fun peekResponse ( response : Response ): PeekedResponse {
85+ if (response.body == null ) return PeekedResponse ( )
6386
64- if (potentialError != null ) {
65- val errorCode = potentialError.groupValues[1 ].toInt()
66- val errorType = ServerErrorType .fromErrorCode(errorCode)
87+ val reader = JsonReader .of(response.peekBody(MAX_PEEK_BYTE_COUNT ).source())
88+ .also { it.beginObject() }
6789
68- if (errorType.isLoginError) {
69- loginTokenManager.persist(null )
70- }
71- } else if (url.pathSegments == LOGIN_URL .pathSegments) {
72- val token = LOGIN_TOKEN_PATTERN .find(responseBody)
90+ var errorCode: Int? = null
91+ var token: String? = null
7392
74- if (token != null ) {
75- loginTokenManager.persist(token.groupValues[1 ])
76- } else {
77- throw JsonDataException (" No token found after successful login." )
93+ while (reader.hasNext() && errorCode == null ) {
94+ when (reader.selectName(OPTIONS )) {
95+ 0 -> errorCode = reader.nextInt()
96+ 1 -> when (reader.peek()) {
97+ JsonReader .Token .BEGIN_OBJECT -> token = peekForToken(reader)
98+ else -> reader.skipValue()
99+ }
100+ else -> {
101+ reader.skipName()
102+ reader.skipValue()
78103 }
79- } else if (url.pathSegments == LOGOUT_URL .pathSegments) {
80- loginTokenManager.persist(null )
81104 }
82105 }
83106
84- return response
107+ return PeekedResponse (errorCode, token)
85108 }
86109
87- private fun peekResponseBody (response : Response ): String {
88- return if (response.body != null ) response.peekBody(MAX_PEEK_BYTE_COUNT ).string() else " "
110+ private fun peekForToken (reader : JsonReader ): String? {
111+ reader.beginObject()
112+
113+ var token: String? = null
114+
115+ while (reader.hasNext()) {
116+ when (reader.selectName(TOKEN_OPTIONS )) {
117+ 0 -> token = reader.nextString()
118+ else -> {
119+ reader.skipName()
120+ reader.skipValue()
121+ }
122+ }
123+ }
124+
125+ reader.endObject()
126+
127+ return token
89128 }
129+
130+ private data class PeekedResponse (val errorCode : Int? = null , val token : String? = null )
90131}
0 commit comments