Skip to content

Commit

Permalink
Add unit tests for Proxy Health Check
Browse files Browse the repository at this point in the history
  • Loading branch information
byronantak committed Dec 2, 2024
1 parent 70730b2 commit 1a6beff
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class LoginAuthenticationCsrfTokenInterceptor implements ClientHttpReques

@Autowired RestTemplateUtil restTemplateUtil;

@Autowired ProxyCheckService proxyCheckService;
@Autowired ProxyHealthCheckService proxyHealthCheckService;

/**
* This is used for the authentication flow to keep things separate from the restTemplate that
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.box.l10n.mojito.rest.resttemplate;

import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class ProxyHealthCheckService implements InitializingBean {

private boolean isHealthy;

@Autowired ResttemplateConfig restTemplateConfig;

@Override
public void afterPropertiesSet() {
RestTemplate restTemplate = buildRestTemplate();
ProxyHealthChecker proxyHealthChecker = new ProxyHealthChecker();
isHealthy = proxyHealthChecker.isProxyHealthy(restTemplate, restTemplateConfig);
}

public boolean isProxyHealthy() {
return isHealthy;
}

/***
* This is needed because the default RestTemplate does not allow the caller
* to set the Host header
*/
private RestTemplate buildRestTemplate() {
CloseableHttpClient httpClient =
HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().build()).build();
return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
}
}
Original file line number Diff line number Diff line change
@@ -1,39 +1,18 @@
package com.box.l10n.mojito.rest.resttemplate;

import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

@Component
public class ProxyCheckService implements InitializingBean {
Logger logger = LoggerFactory.getLogger(ProxyCheckService.class);
public class ProxyHealthChecker {
Logger logger = LoggerFactory.getLogger(ProxyHealthChecker.class);

private boolean hasProxy;

@Autowired ResttemplateConfig restTemplateConfig;

@Override
public void afterPropertiesSet() {
hasProxy = isProxyConfigured();
}

public boolean hasProxy() {
return hasProxy;
}

private boolean isProxyConfigured() {
public boolean isProxyHealthy(RestTemplate restTemplate, ResttemplateConfig restTemplateConfig) {

String testUrl =
UriComponentsBuilder.newInstance()
Expand All @@ -49,9 +28,8 @@ private boolean isProxyConfigured() {
logger.debug("With headers {}", headers);
HttpEntity<String> httpEntity = new HttpEntity<>(null, headers);
try {
RestTemplate tempRestTemplate = buildRestTemplate();
ResponseEntity<Void> response =
tempRestTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, Void.class);
restTemplate.exchange(testUrl, HttpMethod.GET, httpEntity, Void.class);
logger.debug("Proxy login request response code {}", response.getStatusCode());
return response.getStatusCode().is2xxSuccessful();
} catch (Exception e) {
Expand All @@ -61,14 +39,4 @@ private boolean isProxyConfigured() {
return false;
}
}

/***
* This is needed because the default RestTemplate does not allow the caller
* to set the Host header
*/
private RestTemplate buildRestTemplate() {
CloseableHttpClient httpClient =
HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().build()).build();
return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ public class ProxyOutboundRequestInterceptor implements ClientHttpRequestInterce
Logger logger = LoggerFactory.getLogger(ProxyOutboundRequestInterceptor.class);

@Autowired ResttemplateConfig restTemplateConfig;
@Autowired ProxyCheckService proxyCheckService;
@Autowired ProxyHealthCheckService proxyHealthCheckService;

@Override
public ClientHttpResponse intercept(
HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {

if (proxyCheckService.hasProxy()) {
if (proxyHealthCheckService.isProxyHealthy()) {
// To prevent adding extra layers, when the proxied request fails and is retried
if (request.getURI().getHost().equals(restTemplateConfig.getProxyHost())) {
logger.debug("Proxy has already been configured for request");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public Integer getProxyPort() {
return proxyPort;
}

public void setProxyPort(int proxyPort) {
public void setProxyPort(Integer proxyPort) {
this.proxyPort = proxyPort;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.box.l10n.mojito.rest.resttemplate;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

/**
* @author byronantak
*/
class ProxyHealthCheckerTest {

@Mock private RestTemplate restTemplate;

ProxyHealthChecker proxyHealthChecker;

@BeforeEach
void init() {
MockitoAnnotations.openMocks(this);
proxyHealthChecker = new ProxyHealthChecker();
}

@Test
void shouldReturnTrueWhenProxyRequestRespondsWithA200() {
when(restTemplate.exchange(
anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(Void.class)))
.thenReturn(new ResponseEntity<Void>(HttpStatus.OK));

boolean isHealthy = proxyHealthChecker.isProxyHealthy(restTemplate, new ResttemplateConfig());
assertTrue(isHealthy);
}

@Test
void shouldReturnFalseWhenProxyRequestRaisesException() {
when(restTemplate.exchange(
anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(Void.class)))
.thenThrow(new RestClientException("An error occurred"));

boolean isHealthy = proxyHealthChecker.isProxyHealthy(restTemplate, new ResttemplateConfig());
assertFalse(isHealthy);
}

@Test
void shouldReturnFalseWhenProxyRequestReturnsBadStatusCode() {
when(restTemplate.exchange(
anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(Void.class)))
.thenReturn(new ResponseEntity<Void>(HttpStatus.NOT_FOUND));

boolean isHealthy = proxyHealthChecker.isProxyHealthy(restTemplate, new ResttemplateConfig());
assertFalse(isHealthy);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,5 @@ public void testConfig() {
assertEquals("admin", resttemplateConfig.getAuthentication().getUsername());
assertEquals("ChangeMe", resttemplateConfig.getAuthentication().getPassword());
assertEquals("", resttemplateConfig.getContextPath());
assertEquals("localhost", resttemplateConfig.getProxyHost());
assertEquals(Integer.valueOf(19193), resttemplateConfig.getProxyPort());
}
}

0 comments on commit 1a6beff

Please sign in to comment.