Skip to content

Commit 6ca58eb

Browse files
committed
Set Request Headers
1 parent 2ca554c commit 6ca58eb

File tree

6 files changed

+122
-74
lines changed

6 files changed

+122
-74
lines changed

api/src/main/java/ca/bc/gov/educ/api/course/config/RequestInterceptor.java

+21-15
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.springframework.web.servlet.AsyncHandlerInterceptor;
1616

1717
import java.time.Instant;
18+
import java.util.UUID;
1819

1920
@Component
2021
public class RequestInterceptor implements AsyncHandlerInterceptor {
@@ -35,21 +36,30 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
3536
validation.clear();
3637
// correlationID
3738
val correlationID = request.getHeader(EducCourseApiConstants.CORRELATION_ID);
38-
if (correlationID != null) {
39-
ThreadLocalStateUtil.setCorrelationID(correlationID);
39+
ThreadLocalStateUtil.setCorrelationID(correlationID != null ? correlationID : UUID.randomUUID().toString());
40+
41+
//Request Source
42+
val requestSource = request.getHeader(EducCourseApiConstants.REQUEST_SOURCE);
43+
if(requestSource != null) {
44+
ThreadLocalStateUtil.setRequestSource(requestSource);
4045
}
4146

42-
// username
43-
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
44-
if (auth instanceof JwtAuthenticationToken) {
45-
JwtAuthenticationToken authenticationToken = (JwtAuthenticationToken) auth;
46-
Jwt jwt = (Jwt) authenticationToken.getCredentials();
47-
String username = JwtUtil.getName(jwt);
48-
if (username != null) {
49-
ThreadLocalStateUtil.setCurrentUser(username);
47+
// Header userName
48+
val userName = request.getHeader(EducCourseApiConstants.USER_NAME);
49+
if (userName != null) {
50+
ThreadLocalStateUtil.setCurrentUser(userName);
51+
}
52+
else {
53+
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
54+
if (auth instanceof JwtAuthenticationToken) {
55+
JwtAuthenticationToken authenticationToken = (JwtAuthenticationToken) auth;
56+
Jwt jwt = (Jwt) authenticationToken.getCredentials();
57+
String username = JwtUtil.getName(jwt);
58+
if (username != null) {
59+
ThreadLocalStateUtil.setCurrentUser(username);
60+
}
5061
}
5162
}
52-
5363
return true;
5464
}
5565

@@ -64,10 +74,6 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
6474
@Override
6575
public void afterCompletion(@NonNull final HttpServletRequest request, final HttpServletResponse response, @NonNull final Object handler, final Exception ex) {
6676
LogHelper.logServerHttpReqResponseDetails(request, response, constants.isSplunkLogHelperEnabled());
67-
val correlationID = request.getHeader(EducCourseApiConstants.CORRELATION_ID);
68-
if (correlationID != null) {
69-
response.setHeader(EducCourseApiConstants.CORRELATION_ID, request.getHeader(EducCourseApiConstants.CORRELATION_ID));
70-
}
7177
// clear
7278
ThreadLocalStateUtil.clear();
7379
}

api/src/main/java/ca/bc/gov/educ/api/course/config/RestWebClient.java

+15
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package ca.bc.gov.educ.api.course.config;
22

33
import ca.bc.gov.educ.api.course.util.EducCourseApiConstants;
4+
import ca.bc.gov.educ.api.course.util.ThreadLocalStateUtil;
45
import io.netty.handler.logging.LogLevel;
56
import org.springframework.beans.factory.annotation.Autowired;
67
import org.springframework.context.annotation.Bean;
78
import org.springframework.context.annotation.Configuration;
89
import org.springframework.security.oauth2.client.*;
910
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
1011
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
12+
import org.springframework.web.reactive.function.client.ClientRequest;
13+
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
1114
import org.springframework.web.reactive.function.client.ExchangeStrategies;
1215
import org.springframework.web.reactive.function.client.WebClient;
1316
import org.springframework.web.util.DefaultUriBuilderFactory;
@@ -38,6 +41,7 @@ public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager
3841
defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
3942
return WebClient.builder()
4043
.uriBuilderFactory(defaultUriBuilderFactory)
44+
.filter(setRequestHeaders())
4145
.exchangeStrategies(ExchangeStrategies
4246
.builder()
4347
.codecs(codecs -> codecs
@@ -63,4 +67,15 @@ public OAuth2AuthorizedClientManager authorizedClientManager(
6367
return authorizedClientManager;
6468
}
6569

70+
private ExchangeFilterFunction setRequestHeaders() {
71+
return (clientRequest, next) -> {
72+
ClientRequest modifiedRequest = ClientRequest.from(clientRequest)
73+
.header(EducCourseApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID())
74+
.header(EducCourseApiConstants.USER_NAME, ThreadLocalStateUtil.getCurrentUser())
75+
.header(EducCourseApiConstants.REQUEST_SOURCE, EducCourseApiConstants.API_NAME)
76+
.build();
77+
return next.exchange(modifiedRequest);
78+
};
79+
}
80+
6681
}

api/src/main/java/ca/bc/gov/educ/api/course/service/RESTService.java

-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ public <T> T get(String url, Class<T> clazz) {
3939
obj = webClient
4040
.get()
4141
.uri(url)
42-
.headers(h -> h.set(EducCourseApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID()))
4342
.retrieve()
4443
// if 5xx errors, throw Service error
4544
.onStatus(HttpStatusCode::is5xxServerError,
@@ -69,7 +68,6 @@ public <T> T post(String url, Object body, Class<T> clazz) {
6968
try {
7069
obj = webClient.post()
7170
.uri(url)
72-
.headers(h -> h.set(EducCourseApiConstants.CORRELATION_ID, ThreadLocalStateUtil.getCorrelationID()))
7371
.body(BodyInserters.fromValue(body))
7472
.retrieve()
7573
.onStatus(HttpStatusCode::is5xxServerError,

api/src/main/java/ca/bc/gov/educ/api/course/util/EducCourseApiConstants.java

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public class EducCourseApiConstants {
1616
private EducCourseApiConstants() {}
1717

1818
public static final String CORRELATION_ID = "correlationID";
19+
public static final String USER_NAME = "User-Name";
20+
public static final String REQUEST_SOURCE = "Request-Source";
21+
public static final String API_NAME = "EDUC-GRAD-COURSE-API";
1922

2023
//API end-point Mapping constants
2124
public static final String API_ROOT_MAPPING = "";

api/src/main/java/ca/bc/gov/educ/api/course/util/LogHelper.java

+60-52
Original file line numberDiff line numberDiff line change
@@ -10,71 +10,79 @@
1010

1111
import jakarta.servlet.http.HttpServletRequest;
1212
import jakarta.servlet.http.HttpServletResponse;
13+
1314
import java.time.Instant;
1415
import java.util.HashMap;
1516
import java.util.List;
1617
import java.util.Map;
1718

1819
@Slf4j
1920
public final class LogHelper {
20-
private static final ObjectMapper mapper = new ObjectMapper();
21-
private static final String EXCEPTION = "Exception ";
21+
private static final ObjectMapper mapper = new ObjectMapper();
22+
private static final String EXCEPTION = "Exception ";
2223

23-
private LogHelper() {
24+
private LogHelper() {
2425

25-
}
26+
}
2627

27-
public static void logServerHttpReqResponseDetails(@NonNull final HttpServletRequest request, final HttpServletResponse response, final boolean logging) {
28-
if (!logging) return;
29-
try {
30-
final int status = response.getStatus();
31-
val totalTime = Instant.now().toEpochMilli() - (Long) request.getAttribute("startTime");
32-
final Map<String, Object> httpMap = new HashMap<>();
33-
httpMap.put("server_http_response_code", status);
34-
httpMap.put("server_http_request_method", request.getMethod());
35-
httpMap.put("server_http_query_params", request.getQueryString());
36-
val correlationID = request.getHeader(EducCourseApiConstants.CORRELATION_ID);
37-
if (correlationID != null) {
38-
httpMap.put("correlation_id", correlationID);
39-
}
40-
httpMap.put("server_http_request_url", String.valueOf(request.getRequestURL()));
41-
httpMap.put("server_http_request_processing_time_ms", totalTime);
42-
httpMap.put("server_http_request_payload", String.valueOf(request.getAttribute("payload")));
43-
httpMap.put("server_http_request_remote_address", request.getRemoteAddr());
44-
httpMap.put("server_http_request_client_name", StringUtils.trimToEmpty(request.getHeader("X-Client-Name")));
45-
MDC.putCloseable("httpEvent", mapper.writeValueAsString(httpMap));
46-
log.info("");
47-
MDC.clear();
48-
} catch (final Exception exception) {
49-
log.error(EXCEPTION, exception);
28+
public static void logServerHttpReqResponseDetails(@NonNull final HttpServletRequest request, final HttpServletResponse response, final boolean logging) {
29+
if (!logging) return;
30+
try {
31+
final int status = response.getStatus();
32+
val totalTime = Instant.now().toEpochMilli() - (Long) request.getAttribute("startTime");
33+
final Map<String, Object> httpMap = new HashMap<>();
34+
httpMap.put("server_http_response_code", status);
35+
httpMap.put("server_http_request_method", request.getMethod());
36+
httpMap.put("server_http_query_params", request.getQueryString());
37+
val correlationID = request.getHeader(EducCourseApiConstants.CORRELATION_ID);
38+
if (correlationID != null) {
39+
httpMap.put("correlation_id", correlationID);
40+
}
41+
val requestSource = request.getHeader(EducCourseApiConstants.REQUEST_SOURCE);
42+
if (requestSource != null) {
43+
httpMap.put("request_source", requestSource);
44+
}
45+
httpMap.put("server_http_request_url", String.valueOf(request.getRequestURL()));
46+
httpMap.put("server_http_request_processing_time_ms", totalTime);
47+
httpMap.put("server_http_request_payload", String.valueOf(request.getAttribute("payload")));
48+
httpMap.put("server_http_request_remote_address", request.getRemoteAddr());
49+
httpMap.put("server_http_request_client_name", StringUtils.trimToEmpty(request.getHeader("X-Client-Name")));
50+
MDC.putCloseable("httpEvent", mapper.writeValueAsString(httpMap));
51+
log.info("");
52+
MDC.clear();
53+
} catch (final Exception exception) {
54+
log.error(EXCEPTION, exception);
55+
}
5056
}
51-
}
5257

53-
/**
54-
* WebClient to call other REST APIs
55-
*
56-
* @param method
57-
* @param url
58-
* @param responseCode
59-
* @param correlationID
60-
*/
61-
public static void logClientHttpReqResponseDetails(@NonNull final HttpMethod method, final String url, final int responseCode, final List<String> correlationID, final boolean logging) {
62-
if (!logging) return;
63-
try {
64-
final Map<String, Object> httpMap = new HashMap<>();
65-
httpMap.put("client_http_response_code", responseCode);
66-
httpMap.put("client_http_request_method", method.toString());
67-
httpMap.put("client_http_request_url", url);
68-
if (correlationID != null) {
69-
httpMap.put("correlation_id", String.join(",", correlationID));
70-
}
71-
MDC.putCloseable("httpEvent", mapper.writeValueAsString(httpMap));
72-
log.info("");
73-
MDC.clear();
74-
} catch (final Exception exception) {
75-
log.error(EXCEPTION, exception);
58+
/**
59+
* WebClient to call other REST APIs
60+
*
61+
* @param method
62+
* @param url
63+
* @param responseCode
64+
* @param correlationID
65+
*/
66+
public static void logClientHttpReqResponseDetails(@NonNull final HttpMethod method, final String url, final int responseCode, final List<String> correlationID, final List<String> requestSource, final boolean logging) {
67+
if (!logging) return;
68+
try {
69+
final Map<String, Object> httpMap = new HashMap<>();
70+
httpMap.put("client_http_response_code", responseCode);
71+
httpMap.put("client_http_request_method", method.toString());
72+
httpMap.put("client_http_request_url", url);
73+
if (correlationID != null) {
74+
httpMap.put("correlation_id", String.join(",", correlationID));
75+
}
76+
if (requestSource != null) {
77+
httpMap.put("request_source", String.join(",", requestSource));
78+
}
79+
MDC.putCloseable("httpEvent", mapper.writeValueAsString(httpMap));
80+
log.info("");
81+
MDC.clear();
82+
} catch (final Exception exception) {
83+
log.error(EXCEPTION, exception);
84+
}
7685
}
77-
}
7886

7987
/**
8088
* the event is a json string.

api/src/main/java/ca/bc/gov/educ/api/course/util/ThreadLocalStateUtil.java

+23-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
package ca.bc.gov.educ.api.course.util;
22

33
public class ThreadLocalStateUtil {
4-
private static ThreadLocal<String> transaction = new ThreadLocal<>();
5-
private static ThreadLocal<String> user = new ThreadLocal<>();
6-
4+
private static InheritableThreadLocal<String> transaction = new InheritableThreadLocal<>();
5+
private static InheritableThreadLocal<String> user = new InheritableThreadLocal<>();
6+
private static final InheritableThreadLocal<String> requestSource = new InheritableThreadLocal<String>();
77
/**
88
* Set the current correlationID for this thread
99
*
1010
* @param correlationID
1111
*/
12-
public static void setCorrelationID(String correlationID){
12+
public static void setCorrelationID(String correlationID) {
1313
transaction.set(correlationID);
1414
}
1515

@@ -27,7 +27,7 @@ public static String getCorrelationID() {
2727
*
2828
* @param currentUser
2929
*/
30-
public static void setCurrentUser(String currentUser){
30+
public static void setCurrentUser(String currentUser) {
3131
user.set(currentUser);
3232
}
3333

@@ -40,8 +40,26 @@ public static String getCurrentUser() {
4040
return user.get();
4141
}
4242

43+
/**
44+
* Set the requestSource for this thread
45+
*
46+
* @param reqSource
47+
*/
48+
public static void setRequestSource(String reqSource){
49+
requestSource.set(reqSource);
50+
}
51+
/**
52+
* Get the requestSource for this thread
53+
*
54+
* @return the requestSource, or null if it is unknown.
55+
*/
56+
public static String getRequestSource() {
57+
return requestSource.get();
58+
}
59+
4360
public static void clear() {
4461
transaction.remove();
4562
user.remove();
63+
requestSource.remove();
4664
}
4765
}

0 commit comments

Comments
 (0)