Skip to content

Commit 14d8f12

Browse files
committed
Improve login token handling
- The peek byte count has been drastically reduced to avoid OMMs - Empty and non-existing bodies are now handled correctly
1 parent 52c98ea commit 14d8f12

2 files changed

Lines changed: 47 additions & 25 deletions

File tree

library/src/main/java/me/proxer/library/api/LoginTokenInterceptor.java

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
final class LoginTokenInterceptor implements Interceptor {
2222

2323
private static final String LOGIN_TOKEN_HEADER = "proxer-api-token";
24-
private static final int MAX_PEEK_BYTE_COUNT = 1048576;
24+
private static final int MAX_PEEK_BYTE_COUNT = 1024;
2525

2626
private static final Pattern LOGIN_TOKEN_PATTERN = Pattern.compile("\"token\":.*?\"(.+?)\"", DOTALL);
2727
private static final Pattern ERROR_PATTERN = Pattern.compile("\"code\":.*?(\\d+\b?)", DOTALL);
@@ -59,30 +59,7 @@ public Response intercept(final Chain chain) throws IOException {
5959
final Response response = chain.proceed(newRequestBuilder.build());
6060

6161
if (response.isSuccessful()) {
62-
final HttpUrl url = response.request().url();
63-
final String responseBody = response.peekBody(MAX_PEEK_BYTE_COUNT).string();
64-
final Matcher errorMatcher = ERROR_PATTERN.matcher(responseBody);
65-
66-
if (errorMatcher.find()) {
67-
final int errorCode = Integer.parseInt(errorMatcher.group(1));
68-
final ServerErrorType errorType = ServerErrorType.fromErrorCodeOrNull(errorCode);
69-
70-
if (errorType != null && isLoginError(errorType)) {
71-
loginTokenManager.persist(null);
72-
}
73-
74-
return response;
75-
} else if (url.pathSegments().equals(LOGIN_PATH)) {
76-
final Matcher loginTokenMatcher = LOGIN_TOKEN_PATTERN.matcher(responseBody);
77-
78-
if (loginTokenMatcher.find()) {
79-
loginTokenManager.persist(loginTokenMatcher.group(1).trim());
80-
} else {
81-
throw new JsonDataException("No token found after successful login.");
82-
}
83-
} else if (url.pathSegments().equals(LOGOUT_PATH)) {
84-
loginTokenManager.persist(null);
85-
}
62+
if (handleResponse(response)) return response;
8663
}
8764

8865
return response;
@@ -91,6 +68,41 @@ public Response intercept(final Chain chain) throws IOException {
9168
}
9269
}
9370

71+
private boolean handleResponse(Response response) throws IOException {
72+
final String responseBody = peekResponseBody(response);
73+
final Matcher errorMatcher = ERROR_PATTERN.matcher(responseBody);
74+
final HttpUrl url = response.request().url();
75+
76+
if (errorMatcher.find()) {
77+
final int errorCode = Integer.parseInt(errorMatcher.group(1));
78+
final ServerErrorType errorType = ServerErrorType.fromErrorCodeOrNull(errorCode);
79+
80+
if (errorType != null && isLoginError(errorType)) {
81+
loginTokenManager.persist(null);
82+
}
83+
84+
return true;
85+
} else if (url.pathSegments().equals(LOGIN_PATH)) {
86+
final Matcher loginTokenMatcher = LOGIN_TOKEN_PATTERN.matcher(responseBody);
87+
88+
if (loginTokenMatcher.find()) {
89+
loginTokenManager.persist(loginTokenMatcher.group(1).trim());
90+
} else {
91+
throw new JsonDataException("No token found after successful login.");
92+
}
93+
} else if (url.pathSegments().equals(LOGOUT_PATH)) {
94+
loginTokenManager.persist(null);
95+
}
96+
97+
return false;
98+
}
99+
100+
private String peekResponseBody(Response response) throws IOException {
101+
final ResponseBody safeBody = response.body();
102+
103+
return safeBody != null && safeBody.contentLength() > 0 ? response.peekBody(MAX_PEEK_BYTE_COUNT).string() : "";
104+
}
105+
94106
private boolean isLoginError(final ServerErrorType errorType) {
95107
switch (errorType) {
96108
case INVALID_TOKEN:

library/src/test/java/me/proxer/library/api/LoginTokenInterceptorTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import me.proxer.library.ProxerTest;
44
import me.proxer.library.api.ProxerException.ErrorType;
5+
import okhttp3.Request;
56
import okhttp3.mockwebserver.MockResponse;
67
import org.junit.Test;
78

@@ -117,4 +118,13 @@ public void testMalformedResponse() throws IOException, InterruptedException, Pr
117118
.isThrownBy(() -> api.user().login("test", "secret").build().execute())
118119
.matches(exception -> exception.getErrorType() == ErrorType.PARSING);
119120
}
121+
122+
@Test
123+
public void testNoBodyResponse() throws IOException, InterruptedException {
124+
server.enqueue(new MockResponse());
125+
126+
api.client().newCall(new Request.Builder().url("https://proxer.me/fake").build()).execute();
127+
128+
assertThat(server.takeRequest().getHeaders().get("proxer-api-token")).isNull();
129+
}
120130
}

0 commit comments

Comments
 (0)