From f90651c5f9619f156c5d04b0018a815a64d5b04e Mon Sep 17 00:00:00 2001
From: parthiv39731 <70740707+parthiv39731@users.noreply.github.com>
Date: Sat, 18 Nov 2023 12:34:13 +0530
Subject: [PATCH] BAEL-7200 Modify Request Body Before Reaching Controller in
Spring Boot
---
spring-boot-modules/spring-boot-mvc-5/pom.xml | 12 +++
.../modifyrequest/ModifyRequestApp.java | 11 +++
.../modifyrequest/aop/EscapeHtmlAspect.java | 74 +++++++++++++++++++
.../config/WebMvcConfiguration.java | 25 +++++++
.../controller/UserController.java | 23 ++++++
.../filter/EscapeHtmlFilter.java | 27 +++++++
.../EscapeHtmlRequestInterceptor.java | 19 +++++
.../EscapeHtmlRequestWrapper.java | 68 +++++++++++++++++
.../modifyrequest/filter-sequence-design.puml | 31 ++++++++
.../interceptor-sequence-design.puml | 33 +++++++++
.../EscapeHtmlAspectIntegrationTest.java | 52 +++++++++++++
.../EscapeHtmlFilterIntegrationTest.java | 51 +++++++++++++
.../EscapeHtmlInterceptorIntegrationTest.java | 46 ++++++++++++
13 files changed, 472 insertions(+)
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/ModifyRequestApp.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/aop/EscapeHtmlAspect.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/config/WebMvcConfiguration.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/controller/UserController.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/filter/EscapeHtmlFilter.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/interceptor/EscapeHtmlRequestInterceptor.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/filter-sequence-design.puml
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/interceptor-sequence-design.puml
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java
create mode 100644 spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlInterceptorIntegrationTest.java
diff --git a/spring-boot-modules/spring-boot-mvc-5/pom.xml b/spring-boot-modules/spring-boot-mvc-5/pom.xml
index a516cab049..10a58a6a59 100644
--- a/spring-boot-modules/spring-boot-mvc-5/pom.xml
+++ b/spring-boot-modules/spring-boot-mvc-5/pom.xml
@@ -49,6 +49,10 @@
commons-configuration
${commons-configuration.version}
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
@@ -61,6 +65,14 @@
JAR
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 9
+
+
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/ModifyRequestApp.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/ModifyRequestApp.java
new file mode 100644
index 0000000000..7dd937d5b8
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/ModifyRequestApp.java
@@ -0,0 +1,11 @@
+package com.baeldung.modifyrequest;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication(scanBasePackages = "com.baeldung.modifyrequest")
+public class ModifyRequestApp {
+ public static void main(String[] args) {
+ SpringApplication.run(ModifyRequestApp.class, args);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/aop/EscapeHtmlAspect.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/aop/EscapeHtmlAspect.java
new file mode 100644
index 0000000000..fb31abe11b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/aop/EscapeHtmlAspect.java
@@ -0,0 +1,74 @@
+package com.baeldung.modifyrequest.aop;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.MethodParameter;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpInputMessage;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;
+
+import java.io.*;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+
+@RestControllerAdvice
+@Profile("aspectExample")
+public class EscapeHtmlAspect implements RequestBodyAdvice {
+ private static final Logger logger = LoggerFactory.getLogger(EscapeHtmlAspect.class);
+
+ @Override
+ public boolean supports(MethodParameter methodParameter, Type targetType, Class extends HttpMessageConverter>> converterType) {
+ //Apply this to all Controllers
+ return true;
+ }
+
+ @Override
+ public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) throws IOException {
+ logger.info("beforeBodyRead called");
+ InputStream inputStream = inputMessage.getBody();
+ return new HttpInputMessage() {
+ @Override
+ public InputStream getBody() throws IOException {
+ return new ByteArrayInputStream(escapeHtml(inputStream).getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Override
+ public HttpHeaders getHeaders() {
+ return inputMessage.getHeaders();
+ }
+ };
+ }
+
+ @Override
+ public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) {
+ // Return the modified object after reading the body
+ return body;
+ }
+
+ @Override
+ public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class extends HttpMessageConverter>> converterType) {
+ //return the original body
+ return body;
+ }
+
+ private String escapeHtml(InputStream inputStream) throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = null;
+ try (inputStream) {
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ char[] charBuffer = new char[128];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ }
+ String input = stringBuilder.toString();
+ // Escape HTML characters
+ return input.replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">");
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/config/WebMvcConfiguration.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/config/WebMvcConfiguration.java
new file mode 100644
index 0000000000..bd76fd5e55
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/config/WebMvcConfiguration.java
@@ -0,0 +1,25 @@
+package com.baeldung.modifyrequest.config;
+
+import com.baeldung.modifyrequest.interceptor.EscapeHtmlRequestInterceptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@Profile("interceptorExample")
+public class WebMvcConfiguration implements WebMvcConfigurer {
+ private static final Logger logger = LoggerFactory.getLogger(WebMvcConfiguration.class);
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ logger.info("addInterceptors() called");
+ registry.addInterceptor(new EscapeHtmlRequestInterceptor())
+ .addPathPatterns("/save");
+
+ WebMvcConfigurer.super.addInterceptors(registry);
+ }
+}
+
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/controller/UserController.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/controller/UserController.java
new file mode 100644
index 0000000000..26450dd70d
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/controller/UserController.java
@@ -0,0 +1,23 @@
+package com.baeldung.modifyrequest.controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/")
+public class UserController {
+ Logger logger = LoggerFactory.getLogger(UserController.class);
+
+ @PostMapping(value = "save")
+ public ResponseEntity saveUser(@RequestBody String user) {
+ logger.info("save user info into database");
+ ResponseEntity responseEntity = new ResponseEntity<>(user, HttpStatus.CREATED);
+ return responseEntity;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/filter/EscapeHtmlFilter.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/filter/EscapeHtmlFilter.java
new file mode 100644
index 0000000000..45cad3be1c
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/filter/EscapeHtmlFilter.java
@@ -0,0 +1,27 @@
+package com.baeldung.modifyrequest.filter;
+
+import com.baeldung.modifyrequest.requestwrapper.EscapeHtmlRequestWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+@Component
+@Order(1)
+@Profile("filterExample")
+public class EscapeHtmlFilter implements Filter {
+ Logger logger = LoggerFactory.getLogger(EscapeHtmlFilter.class);
+
+ @Override
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ logger.info("Modify the request");
+
+ filterChain.doFilter(new EscapeHtmlRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/interceptor/EscapeHtmlRequestInterceptor.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/interceptor/EscapeHtmlRequestInterceptor.java
new file mode 100644
index 0000000000..1ad39605e5
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/interceptor/EscapeHtmlRequestInterceptor.java
@@ -0,0 +1,19 @@
+package com.baeldung.modifyrequest.interceptor;
+
+import com.baeldung.modifyrequest.requestwrapper.EscapeHtmlRequestWrapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class EscapeHtmlRequestInterceptor implements HandlerInterceptor {
+ private static final Logger logger = LoggerFactory.getLogger(EscapeHtmlRequestInterceptor.class);
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ EscapeHtmlRequestWrapper escapeHtmlRequestWrapper = new EscapeHtmlRequestWrapper(request);
+ return true;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java
new file mode 100644
index 0000000000..65c758d956
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/java/com/baeldung/modifyrequest/requestwrapper/EscapeHtmlRequestWrapper.java
@@ -0,0 +1,68 @@
+package com.baeldung.modifyrequest.requestwrapper;
+
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.*;
+
+public class EscapeHtmlRequestWrapper extends HttpServletRequestWrapper {
+ private String body = null;
+ public EscapeHtmlRequestWrapper(HttpServletRequest request) throws IOException {
+ super(request);
+ this.body = this.escapeHtml(request);
+ }
+
+ private String escapeHtml(HttpServletRequest request) throws IOException {
+ StringBuilder stringBuilder = new StringBuilder();
+ BufferedReader bufferedReader = null;
+ try (InputStream inputStream = request.getInputStream()) {
+ bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ char[] charBuffer = new char[128];
+ int bytesRead = -1;
+ while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
+ stringBuilder.append(charBuffer, 0, bytesRead);
+ }
+ }
+ String input = stringBuilder.toString();
+ // Escape HTML characters
+ return input.replaceAll("&", "&")
+ .replaceAll("<", "<")
+ .replaceAll(">", ">")
+ //.replaceAll("\"", """)
+ .replaceAll("'", "'");
+ }
+
+ @Override
+ public ServletInputStream getInputStream() {
+ final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
+ ServletInputStream servletInputStream = new ServletInputStream() {
+
+ @Override
+ public int read() {
+ return byteArrayInputStream.read();
+ }
+
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+
+ @Override
+ public boolean isReady() {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener listener) {
+
+ }
+ };
+ return servletInputStream;
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException {
+ return new BufferedReader(new InputStreamReader(this.getInputStream()));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/filter-sequence-design.puml b/spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/filter-sequence-design.puml
new file mode 100644
index 0000000000..41689ac723
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/filter-sequence-design.puml
@@ -0,0 +1,31 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+skinparam sequenceMessageAlign direction
+skinparam handwritten true
+skinparam sequence {
+ParticipantBackgroundColor beige
+ParticipantPadding 50
+}
+
+autonumber
+
+Browser -[#63b175]> Filter: HTTP Request
+activate Browser
+activate Filter
+Filter -[#63b175]> Filter: doFilter()
+Filter -[#63b175]> DispatcherServlet: HTTP Request
+activate DispatcherServlet
+
+
+DispatcherServlet -[#63b175]> Controller: HTTP Request
+activate Controller
+Controller --[#63b175]> DispatcherServlet: HTTP Response
+deactivate Controller
+
+DispatcherServlet --[#63b175]> Filter: HTTP Response
+deactivate DispatcherServlet
+
+Filter --[#63b175]> Browser: HTTP Response
+deactivate Filter
+deactivate Browser
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/interceptor-sequence-design.puml b/spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/interceptor-sequence-design.puml
new file mode 100644
index 0000000000..429b8182ca
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/main/resources/modifyrequest/interceptor-sequence-design.puml
@@ -0,0 +1,33 @@
+@startuml
+'https://plantuml.com/sequence-diagram
+skinparam sequenceMessageAlign direction
+skinparam handwritten true
+skinparam sequence {
+ParticipantBackgroundColor beige
+ParticipantPadding 50
+}
+
+autonumber
+
+Browser -[#63b175]> Filter: Http Request
+activate Browser
+activate Filter
+Filter -[#63b175]> DispatcherServlet: Http Request
+activate DispatcherServlet
+
+DispatcherServlet -[#63b175]> Interceptor: Http Request
+activate Interceptor
+Interceptor -[#63b175]> Interceptor: preHandle()
+Interceptor -[#63b175]> Controller: Http Request
+activate Controller
+Controller --[#63b175]> Interceptor: Http Response
+deactivate Controller
+Interceptor --[#63b175]> DispatcherServlet: Http Response
+deactivate Interceptor
+DispatcherServlet --[#63b175]> Filter: Http Response
+deactivate DispatcherServlet
+
+Filter --[#63b175]> Browser: Http Response
+deactivate Filter
+deactivate Browser
+@enduml
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java
new file mode 100644
index 0000000000..665733c61b
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlAspectIntegrationTest.java
@@ -0,0 +1,52 @@
+package com.baeldung.modifyrequest;
+
+import com.baeldung.modifyrequest.controller.UserController;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+import java.net.URI;
+import java.util.Map;
+
+@ExtendWith(SpringExtension.class)
+@AutoConfigureMockMvc
+@WebMvcTest(UserController.class)
+@ActiveProfiles("aspectExample")
+public class EscapeHtmlAspectIntegrationTest {
+ Logger logger = LoggerFactory.getLogger(EscapeHtmlAspectIntegrationTest.class);
+
+ @Autowired
+ private MockMvc mockMvc;
+ @Test
+ void givenAspect_whenEscapeHtmlAspect_thenEscapeHtml() throws Exception {
+
+ Map requestBody = Map.of(
+ "name", "James Cameron",
+ "email", "james@gmail.com"
+ );
+
+ Map expectedResponseBody = Map.of(
+ "name", "James Cameron",
+ "email", "<script>alert()</script>james@gmail.com"
+ );
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ mockMvc.perform(MockMvcRequestBuilders.post(URI.create("/save"))
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(requestBody)))
+ .andExpect(MockMvcResultMatchers.status().isCreated())
+ .andExpect(MockMvcResultMatchers.content().json(objectMapper.writeValueAsString(expectedResponseBody)));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java
new file mode 100644
index 0000000000..35254eb151
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlFilterIntegrationTest.java
@@ -0,0 +1,51 @@
+package com.baeldung.modifyrequest;
+
+import com.baeldung.modifyrequest.controller.UserController;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+import java.net.URI;
+import java.util.Map;
+
+@ExtendWith(SpringExtension.class)
+@AutoConfigureMockMvc
+@WebMvcTest(UserController.class)
+@ActiveProfiles("filterExample")
+public class EscapeHtmlFilterIntegrationTest {
+ Logger logger = LoggerFactory.getLogger(EscapeHtmlFilterIntegrationTest.class);
+
+ @Autowired
+ private MockMvc mockMvc;
+ @Test
+ void givenFilter_whenEscapeHtmlFilter_thenEscapeHtml() throws Exception {
+ Map requestBody = Map.of(
+ "name", "James Cameron",
+ "email", "james@gmail.com"
+ );
+
+ Map expectedResponseBody = Map.of(
+ "name", "James Cameron",
+ "email", "<script>alert()</script>james@gmail.com"
+ );
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ mockMvc.perform(MockMvcRequestBuilders.post(URI.create("/save"))
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(requestBody)))
+ .andExpect(MockMvcResultMatchers.status().isCreated())
+ .andExpect(MockMvcResultMatchers.content().json(objectMapper.writeValueAsString(expectedResponseBody)));
+ }
+}
diff --git a/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlInterceptorIntegrationTest.java b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlInterceptorIntegrationTest.java
new file mode 100644
index 0000000000..002481de4f
--- /dev/null
+++ b/spring-boot-modules/spring-boot-mvc-5/src/test/java/com/baeldung/modifyrequest/EscapeHtmlInterceptorIntegrationTest.java
@@ -0,0 +1,46 @@
+package com.baeldung.modifyrequest;
+
+import com.baeldung.modifyrequest.controller.UserController;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+import java.net.URI;
+import java.util.Map;
+
+
+@ExtendWith(SpringExtension.class)
+@AutoConfigureMockMvc
+@WebMvcTest(UserController.class)
+@ActiveProfiles("interceptorExample")
+public class EscapeHtmlInterceptorIntegrationTest {
+ Logger logger = LoggerFactory.getLogger(EscapeHtmlInterceptorIntegrationTest.class);
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ void givenInterceptor_whenEscapeHtmlInterceptor_thenEscapeHtml() throws Exception {
+ Map requestBody = Map.of(
+ "name", "James Cameron",
+ "email", "james@gmail.com"
+ );
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ mockMvc.perform(MockMvcRequestBuilders.post(URI.create("/save"))
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(requestBody)))
+ .andExpect(MockMvcResultMatchers.status().is4xxClientError());
+ }
+}