mirror of
https://github.com/imgfloat/server.git
synced 2026-02-05 03:39:26 +00:00
Add request logging
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package com.imgfloat.app.config;
|
package com.imgfloat.app.config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -26,23 +27,72 @@ class TwitchOAuth2ErrorResponseErrorHandler extends OAuth2ErrorResponseErrorHand
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleError(ClientHttpResponse response) throws IOException {
|
public void handleError(ClientHttpResponse response) throws IOException {
|
||||||
|
byte[] bodyBytes = StreamUtils.copyToByteArray(response.getBody());
|
||||||
|
String body = new String(bodyBytes, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
if (body.isBlank()) {
|
||||||
|
LOG.warn("Failed to parse Twitch OAuth error response (status: {}, headers: {}): <empty body>",
|
||||||
|
response.getStatusCode(),
|
||||||
|
response.getHeaders());
|
||||||
|
throw asAuthorizationException(body, null);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
super.handleError(response);
|
super.handleError(new CachedBodyClientHttpResponse(response, bodyBytes));
|
||||||
} catch (HttpMessageNotReadableException ex) {
|
} catch (HttpMessageNotReadableException | IllegalArgumentException ex) {
|
||||||
String body = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
|
|
||||||
LOG.warn("Failed to parse Twitch OAuth error response (status: {}, headers: {}): {}",
|
LOG.warn("Failed to parse Twitch OAuth error response (status: {}, headers: {}): {}",
|
||||||
response.getStatusCode(),
|
response.getStatusCode(),
|
||||||
response.getHeaders(),
|
response.getHeaders(),
|
||||||
body.isBlank() ? "<empty body>" : body,
|
body,
|
||||||
ex);
|
ex);
|
||||||
throw asAuthorizationException(body, ex);
|
throw asAuthorizationException(body, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private OAuth2AuthorizationException asAuthorizationException(String body,
|
private OAuth2AuthorizationException asAuthorizationException(String body, Exception ex) {
|
||||||
HttpMessageNotReadableException ex) {
|
|
||||||
String description = "Failed to parse Twitch OAuth error response" + (body.isBlank() ? "." : ": " + body);
|
String description = "Failed to parse Twitch OAuth error response" + (body.isBlank() ? "." : ": " + body);
|
||||||
OAuth2Error oauth2Error = new OAuth2Error("invalid_token_response", description, null);
|
OAuth2Error oauth2Error = new OAuth2Error("invalid_token_response", description, null);
|
||||||
return new OAuth2AuthorizationException(oauth2Error, ex);
|
return new OAuth2AuthorizationException(oauth2Error, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class CachedBodyClientHttpResponse implements ClientHttpResponse {
|
||||||
|
|
||||||
|
private final ClientHttpResponse delegate;
|
||||||
|
private final byte[] body;
|
||||||
|
|
||||||
|
private CachedBodyClientHttpResponse(ClientHttpResponse delegate, byte[] body) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.springframework.http.HttpStatusCode getStatusCode() throws IOException {
|
||||||
|
return delegate.getStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawStatusCode() throws IOException {
|
||||||
|
return delegate.getRawStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStatusText() throws IOException {
|
||||||
|
return delegate.getStatusText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
delegate.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.io.InputStream getBody() throws IOException {
|
||||||
|
return new ByteArrayInputStream(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.springframework.http.HttpHeaders getHeaders() {
|
||||||
|
return delegate.getHeaders();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.imgfloat.app.config;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.RequestEntity;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.mock.http.client.MockClientHttpResponse;
|
||||||
|
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
|
||||||
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||||
|
import org.springframework.test.web.client.MockRestServiceServer;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
|
||||||
|
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
|
||||||
|
|
||||||
|
class TwitchOAuth2ErrorResponseErrorHandlerTest {
|
||||||
|
|
||||||
|
private final TwitchOAuth2ErrorResponseErrorHandler handler = new TwitchOAuth2ErrorResponseErrorHandler();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void fallsBackToSyntheticErrorWhenErrorBodyIsMissing() throws Exception {
|
||||||
|
MockClientHttpResponse response = new MockClientHttpResponse(new byte[0], HttpStatus.BAD_REQUEST);
|
||||||
|
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
OAuth2AuthorizationException exception = assertThrows(OAuth2AuthorizationException.class,
|
||||||
|
() -> handler.handleError(response));
|
||||||
|
|
||||||
|
assertThat(exception.getError().getErrorCode()).isEqualTo("invalid_token_response");
|
||||||
|
assertThat(exception.getError().getDescription())
|
||||||
|
.contains("Failed to parse Twitch OAuth error response");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void successfulResponsesStillParseNormally() {
|
||||||
|
RestTemplate restTemplate = OAuth2RestTemplateFactory.create();
|
||||||
|
restTemplate.setErrorHandler(new TwitchOAuth2ErrorResponseErrorHandler());
|
||||||
|
MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build();
|
||||||
|
|
||||||
|
server.expect(requestTo("https://id.twitch.tv/oauth2/token"))
|
||||||
|
.andRespond(withSuccess(
|
||||||
|
"{\"access_token\":\"abc\",\"token_type\":\"bearer\",\"expires_in\":3600,\"scope\":[]}",
|
||||||
|
MediaType.APPLICATION_JSON));
|
||||||
|
|
||||||
|
RequestEntity<Void> request = RequestEntity.post(URI.create("https://id.twitch.tv/oauth2/token")).build();
|
||||||
|
ResponseEntity<OAuth2AccessTokenResponse> response = restTemplate.exchange(request, OAuth2AccessTokenResponse.class);
|
||||||
|
|
||||||
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
assertThat(response.getBody()).isNotNull();
|
||||||
|
assertThat(response.getBody().getAccessToken().getTokenValue()).isEqualTo("abc");
|
||||||
|
|
||||||
|
server.verify();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user