YahooFinanceRestTemplateConfiguration.java
package com.tdmconsult.ete.services.yahoo;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriComponentsBuilder;
@Configuration
@EnableConfigurationProperties(YahooFinanceProperties.class)
@Slf4j
public class YahooFinanceRestTemplateConfiguration {
@Bean
RestTemplate yahooFinanceRestTemplate(
final RestTemplateBuilder builder,
final YahooFinanceProperties yahooFinanceProperties,
final YahooFinanceSessionService authenticationService) {
ClientHttpRequestInterceptor interceptor = (request, body, execution) -> {
final var response = execute(authenticationService, request, body, execution);
if (response.getStatusCode() == UNAUTHORIZED || response.getStatusCode() == FORBIDDEN) {
// 2nd try after session invalidation
authenticationService.invalidateSession();
return execute(authenticationService, request, body, execution);
}
return response;
};
return builder
.uriTemplateHandler(new DefaultUriBuilderFactory(yahooFinanceProperties.baseurl() + "/v10/finance/"))
.requestFactory(() ->
new BufferingClientHttpRequestFactory(
new SimpleClientHttpRequestFactory()))
.additionalInterceptors(interceptor, new JsonLoggingInterceptor())
.build();
}
private static ClientHttpResponse execute(
final YahooFinanceSessionService authenticationService,
final HttpRequest request,
final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
final var session = authenticationService.getSession();
request.getHeaders().set(
HttpHeaders.USER_AGENT,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
request.getHeaders().set(
HttpHeaders.COOKIE,
session.cookie());
final var uri = UriComponentsBuilder
.fromUri(request.getURI())
.queryParam("crumb", session.crumb())
.build(true)
.toUri();
final var wrapper = new HttpRequestWrapper(request) {
@Override
public URI getURI() {
return uri;
}
};
return execution.execute(wrapper, body);
}
public static class JsonLoggingInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(
final HttpRequest request,
final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
ClientHttpResponse response = execution.execute(request, body);
MediaType contentType = response.getHeaders().getContentType();
if (contentType != null
&& MediaType.APPLICATION_JSON.includes(contentType)) {
String json = StreamUtils.copyToString(
response.getBody(),
StandardCharsets.UTF_8);
log.trace(request.getMethod() + ": " + request.getURI());
log.trace("Status: " + response.getStatusCode());
log.trace(json);
}
return response;
}
}
}