How to access request headers in implementation of WriterInterceptor interface in JAX-RS?
context.getHeaders(); //This line gives a set of response headers(not request headers) in the WriterInterceptor implementation.
Complete code below:
public class GzipFilterWriterInterceptor implements WriterInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(GzipFilterWriterInterceptor.class);
#Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
MultivaluedMap<String,Object> headers = context.getHeaders();
headers.add("Content-Encoding", "gzip");
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
context.proceed();
}
}
You can just inject HttpHeaders. It will be a thread-local proxy when it's injected, so it's thread safe.
#Context
private HttpHeaders headers;
It has methods
String getHeaderString(String name)
List<String> getRequestHeader(String name)
MultivaluedMap<String,String> getRequestHeaders()
UPDATE (test)
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import java.io.IOException;
import java.util.logging.Logger;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
/**
* Run like any other JUnit test. Only one required dependency:
*
* <dependency>
* <groupId>org.glassfish.jersey.test-framework.providers</groupId>
* <artifactId>jersey-test-framework-provider-inmemory</artifactId>
* <scope>test</scope>
* <version>${jersey.version}</version>
* </dependency>
*/
public class HeadersTest extends JerseyTest {
#Path("hello")
public static class HelloResource {
#GET
public String get() {
return "Hello";
}
}
#Override
public ResourceConfig configure() {
return new ResourceConfig(HelloResource.class)
.register(HeaderWriter.class)
.register(new LoggingFilter(Logger.getAnonymousLogger(), true));
}
#Provider
public static class HeaderWriter implements WriterInterceptor {
#Context
private HttpHeaders headers;
#Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException {
context.proceed();
final String header = headers.getHeaderString("X-Request-Header");
context.getHeaders().add("X-Response-Header", header);
}
}
#Test
public void doit() {
final Response response = target("hello").request()
.header("X-Request-Header", "BooYah")
.get();
assertThat(response.getHeaderString("X-Response-Header"), is("BooYah"));
}
}
You can implement below code to ,see working example at http://jerseyexample-ravikant.rhcloud.com/rest/jws/say/Hello
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
#Provider
public class SecurityInterceptor implements ContainerRequestFilter, ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext reqCtx, ContainerResponseContext respCtx) throws IOException {
long startTime=0;
System.out.println("Adding ProcessingTime in response headers");
if(reqCtx.getHeaderString("startTime")!=null)
startTime = Long.parseLong(reqCtx.getHeaderString("startTime"));
respCtx.getHeaders().add("ProcessingTime",
String.valueOf(System.currentTimeMillis() - startTime) + " millisecs");
}
#Override
public void filter(ContainerRequestContext reqCtx) throws IOException {
System.out.println("Adding start time in request headers");
reqCtx.getHeaders().add("startTime", String.valueOf(System.currentTimeMillis()));
}
}
#Provider
public class GzipFilterWriterInterceptor implements WriterInterceptor
{
private static final Logger LOG = LoggerFactory.getLogger(GzipFilterWriterInterceptor.class);
// use a context injection
#Context
private HttpHeaders httpHeaders;
#Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException
{
MultivaluedMap<String,Object> headers = context.getHeaders();
headers.add("Content-Encoding", "gzip");
// do stuff with headers
if ("Basic Ym9iOnBhc3N3b3Jk".equals(httpHeaders.getRequestHeader("Authorization").get(0)))
{
//do stuff here, but be careful about the indexoutofbounds...
}
final OutputStream outputStream = context.getOutputStream();
context.setOutputStream(new GZIPOutputStream(outputStream));
context.proceed();
}
}
The context injection will be injected per request, see the javadocs.
Probably not best solution, but you can have your interceptor implementing ReaderInterceptor. There you can get headers and save them in ThreadLocal variable so you can access then in WriterInterceptor
Also if you have annotation based configuration you can try to inject ContainerRequestContext with a #Context annotation
Related
Is there a way to add a filter/interceptor to static resources served from META-INF/resources?
I seem have tried all the possible options: #ServerResponseFilter, ContainerResponseFilter,WriterInterceptor however all these functions are called only for #Path or #Route...
Is there anything similar to #RouteFilter but for response?
Those are the only ones available:
public interface ClientRequestFilter {
void filter(ClientRequestContext requestContext) throws IOException;
}
public interface ClientResponseFilter {
void filter(ClientRequestContext requestContext,
ClientResponseContext responseContext) throws IOException;
}
public interface ContainerRequestFilter {
void filter(ContainerRequestContext requestContext) throws IOException;
}
public interface ContainerResponseFilter {
void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) throws IOException;
}
public interface ReaderInterceptor {
Object aroundReadFrom(ReaderInterceptorContext context)
throws java.io.IOException, javax.ws.rs.WebApplicationException;
}
public interface WriterInterceptor {
void aroundWriteTo(WriterInterceptorContext context)
throws java.io.IOException, javax.ws.rs.WebApplicationException;
}
You could try with ClientResponseFilter and see:
In the Client API, a ClientRequestFilter is executed as part of the
invocation pipeline, before the HTTP request is delivered to the
network.
ClientResponseFilter is executed upon receiving a server response,
before control is returned to the application.
https://quarkus.io/specs/jaxrs/2.1/index.html#filters_and_interceptors
There seem to be nothing built-in to modify the response of a static content for now but nothing stops you from serving content in a dynamic way:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
#Path("/")
#Produces(MediaType.TEXT_HTML)
public class FrontendController {
#GET
public Response index() throws IOException {
try (var index = getClass().getResourceAsStream(FrontendConstants.INDEX_RESOURCE)) {
if (index == null) {
throw new IOException("index.html file does not exist");
}
//modify index
return Response
.ok(index)
.cacheControl(FrontendConstants.NO_CACHE)
.build();
}
}
#GET
#Path("/{fileName:.+}")
public Response staticFile(#PathParam("fileName") String fileName) throws IOException {
try (var file = FrontendController.class.getResourceAsStream(FrontendConstants.FRONTEND_DIR + "/" + fileName)) {
if (file == null) {
return index();
}
var contentType = URLConnection.guessContentTypeFromStream(file);
return Response
.ok(
new String(file.readAllBytes(), StandardCharsets.UTF_8),
contentType == null ? MediaType.TEXT_PLAIN : contentType
)
.cacheControl(FrontendConstants.NO_CACHE)
.build();
}
}
}
I have a self contained Jersey test using JerseyExtension (JerseyExtension) with JUnit5 (since JerseyTest does not work with JUnit5 unless you use the vintage engine) and subsequent calls to the container are getting different session. Is there a way to keep the session store same between the calls?
package com.test.jerseysession;
import com.github.hanleyt.JerseyExtension;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.RegisterExtension;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class JerseyTestWithGrizzly {
private final static TestContainerFactory testContainerFactory;
private final ServletContainer servletContainer;
private final ResourceConfig resourceConfig;
private final DeploymentContext deploymentContext;
static {
testContainerFactory = new GrizzlyWebTestContainerFactory();
}
#RegisterExtension
#SuppressWarnings("unused")
JerseyExtension jerseyExtension = new JerseyExtension(
this::getTestContainerFactory,
this::configureDeploymentContext,
this::configureJerseyClient);
public JerseyTestWithGrizzly() {
this.resourceConfig = new ResourceConfig()
.packages("com.test.jerseysession")
.register(getClass());
this.servletContainer = new ServletContainer(resourceConfig);
this.deploymentContext = ServletDeploymentContext.builder(resourceConfig)
.servlet(servletContainer)
.servletPath("api")
.build();
}
#Path("session")
public static class SessionResource {
#GET
public String get(#Context HttpServletRequest request) {
HttpSession session = request.getSession(true);
Object obj = session.getAttribute("name");
return session.getId() + ": " + obj;
}
#PUT
public String put(#Context HttpServletRequest request) {
HttpSession session = request.getSession(true);
session.setAttribute("name", "foo");
return session.getId()+": Set name attribute called";
}
}
protected ClientConfig configureJerseyClient(ExtensionContext extensionContext, ClientConfig clientConfig) {
assertNotNull(extensionContext);
assertNotNull(clientConfig);
return clientConfig;
}
protected DeploymentContext configureDeploymentContext(ExtensionContext extensionContext) {
assertNotNull(extensionContext);
return deploymentContext;
}
protected TestContainerFactory getTestContainerFactory(ExtensionContext extensionContext) {
assertNotNull(extensionContext);
return testContainerFactory;
}
#Test
public void testSessionSet(WebTarget target) {
// Call PUT which sets attribute called 'name'
Response response0 = target.path("session").request().put(Entity.entity("{}", MediaType.APPLICATION_JSON_TYPE));
System.out.println("PUT: status="+response0.getStatus()+" response="+response0.readEntity(String.class));
// Call GET which should be able to find 'name' in session set by previous call
Response response1 = target.path("session").request().get();
System.out.println("GET: status="+response1.getStatus()+" response="+response1.readEntity(String.class));
}
}
Sample output:
PUT: status=200 response=8373522406385125383: Set name attribute called
GET: status=200 response=8264425692811867393: null
The session ID changed between the call to PUT and GET.
The client used by Jersey test framework, does not behave like a browser when it comes to Set-Cookie/Cookie headers. The two requests are not connected and JSESSIONID set by first response is not propagated to next request. While the framework is aware of the JSESSIONID if present, it does not span requests and needs to be manually copied forward.
Changing the test method to following works:
#Test
public void testSessionSet(WebTarget target) {
Response response0 = target.path("session").request().put(Entity.entity("{}", MediaType.APPLICATION_JSON_TYPE));
System.out.println("PUT: status="+response0.getStatus()+" response="+response0.readEntity(String.class));
Invocation.Builder nextRequestBuilder = target.path("session").request();
NewCookie jsessionid = response0.getCookies().get("JSESSIONID");
if (jsessionid != null) {
nextRequestBuilder.cookie(jsessionid);
}
Response response1 = nextRequestBuilder.get();
System.out.println("GET: status="+response1.getStatus()+" response="+response1.readEntity(String.class));
}
I want to build a REST api in Spring Webflux using functional endpoints. For CORS I use a WebFilter corsFilter method which sets the required headers. I do see that the method is called (I see the log messages from it) and I see that the headers on the response are indeed the ones I set in my Webflux api. However, as soon as I started to use the corsFilter the requests return 404 status (earlier they would return JSON). I suspect that corsFilter doesn't pass over the request to the router functions. Why would that be?
Specifically I'm wondering if this line is enough to connect the cors config with the routes:
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(RouterFunctions.toWebHandler(route))
.applicationContext(ctx).build();
This is my main class:
package com.mypackage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import reactor.ipc.netty.http.server.HttpServer;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
import static org.springframework.web.reactive.function.server.RequestPredicates.method;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler;
#SpringBootApplication
public class Server {
private static final Logger log = LogManager.getLogger(Server.class);
public static final String HOST = "localhost";
public static final int PORT = 8080;
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CorsConfiguration.class);
Server server = new Server();
server.startReactorServer(ctx);
System.out.println("Press ENTER to exit.");
System.in.read();
}
public RouterFunction<ServerResponse> routingFunction() {
PersonRepository repository = new DummyPersonRepository();
PersonHandler handler = new PersonHandler(repository);
return nest(path("/person"),
nest(accept(APPLICATION_JSON),
route(GET("/{id}"), handler::getPerson)
.andRoute(method(HttpMethod.GET), handler::listPeople)
).andRoute(POST("/").and(contentType(APPLICATION_JSON)), handler::createPerson));
}
public void startReactorServer(AnnotationConfigApplicationContext ctx) {
RouterFunction<ServerResponse> route = this.routingFunction().filter((request, next) -> {
log.warn(request.path());
if (request.path().contains("person")) {
log.warn("calling next()");
return next.handle(request);
} else {
return ServerResponse.status(UNAUTHORIZED).build();
}
});
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(RouterFunctions.toWebHandler(route))
.applicationContext(ctx).build();
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
HttpServer server = HttpServer.create(HOST, PORT);
server.newHandler(adapter).block();
}
}
and this is my CORS config class:
package com.mypackage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
#Configuration
#EnableWebFlux
public class CorsConfiguration {
private static final Logger log = LogManager.getLogger(CorsConfiguration.class);
private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN, mode";
private static final String ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS";
private static final String ALLOWED_ORIGIN = "*";
private static final String MAX_AGE = "3600";
#Bean
public WebFilter corsFilter() {
log.warn("from CorsConfiguration!!!");
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
log.warn("after ServerHttpRequest");
if (CorsUtils.isCorsRequest(request)) {
log.warn("inside isCorsRequest");
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}
To use the functional approach when defining your endpoints Spring Boot's official documentation has a very simple example.
FooBarApplication.class this is our main class.
#SpringBootApplication
public class FooBarApplication {
public static void main(String[] args) {
SpringApplication.run(FooBarApplication.class, args);
}
}
RoutingConfiguration.class (or whatever you wanna call it)
#Configuration
public class RoutingConfiguration {
#Bean
public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
.andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
.andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
}
}
#Component
public class UserHandler {
public Mono<ServerResponse> getUser(ServerRequest request) {
// ...
}
public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
// ...
}
public Mono<ServerResponse> deleteUser(ServerRequest request) {
// ...
}
}
any class annotated with #Configuration will be run at startup and run all #Bean annotated methods. So this will run the monoRouterFunction and set up all our routes for us.
Example taken from the official spring boot documentation Spring boot webflux scroll down a little bit.
EDIT:
and as a side note the #EnableWebFlux annotation means that you will disable the auto-configuration of webflux and set upp configuration manually. I do not recommend this if you are just starting out (i know the name is very misleading) you can read about the webflux auto-configuration here Spring WebFlux Auto-configuration
EDIT2:
WebFlux has a built in CorsFilter that you can use all you need is to configure it.
#Bean
CorsWebFilter corsWebFilter() {
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowedOrigins(Arrays.asList("http://allowed-origin.com"));
corsConfig.setMaxAge(8000L);
corsConfig.addAllowedMethod("PUT");
corsConfig.addAllowedHeader("Baeldung-Allowed");
UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return new CorsWebFilter(source);
}
Example taken from Enabling CORS with a WebFilter
I want to attach a request-response-http to the allure-report from citrus-framework.
I wrote this class.
package com.cdek.qa_auto.common;
import io.qameta.allure.attachment.DefaultAttachmentProcessor;
import io.qameta.allure.attachment.FreemarkerAttachmentRenderer;
import io.qameta.allure.attachment.http.HttpRequestAttachment;
import io.qameta.allure.attachment.http.HttpResponseAttachment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.FileCopyUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
public class CustomCitrusHttpInterceptor implements ClientHttpRequestInterceptor {
private String requestTemplatePath = "http-request.ftl";
private String responseTemplatePath = "http-response.ftl";
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
handleRequest(getRequestContent(request, new String(body)));
ClientHttpResponse response = execution.execute(request, body);
CachingClientHttpResponseWrapper bufferedResponse = new CachingClientHttpResponseWrapper(response);
handleResponse(getResponseContent(bufferedResponse));
return bufferedResponse;
}
}
and test
#SpringBootTest
#ExtendWith(CitrusExtension.class)
public class CitrusLogTest {
#Test
#com.consol.citrus.annotations.CitrusTest
void testPost1(#CitrusResource TestRunner runner) {
HttpClient todoClient = CitrusEndpoints
.http()
.client()
.interceptor(new CustomCitrusHttpInterceptor())
.requestUrl("http://address")
.build();
runner.http(action -> action
.client(todoClient)
.send()
.post("/api/tokenauth/authorize")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.payload("{ \n" +
" \"user\":\"User\",\n" +
" \"hashedPass\":\"hashedPass\"\n" +
"}"));
runner.http(action -> action
.client(todoClient)
.receive()
.response(HttpStatus.OK)
.messageType(MessageType.JSON)
.validationCallback(new AbstractValidationCallback<String>() {
#Override
public void validate(String payload, Map<String, Object> headers, TestContext context) {
assertTrue(payload.contains("token"));
}
}));
}
}
After run test, request-response-http was not in the allure-report.
In debug, in CustomCitrusHttpInterceptor does not come.
I expect the request-response-http to be in the allure-report.
HttpClient build = CitrusEndpoints
.http()
.client()
.build();
build.getEndpointConfiguration().setClientInterceptors(Collections.singletonList(new CustomCitrusHttpInterceptor()));
The request-response-http was in the allure-report.
I want to add a client name parameter to my URL, so when i receive a link like :
http://localhost:8080/client1 i want to test if my client is present in database, if so i want that the client receive the content of my site like if he call :
http://localhost:8080/
I tried to do this with a wrapper like indicated here :
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ChangeURIPathFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(ChangeURIPathFilter.class);
RequestWrapper modifiedRequest = null;
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String contextPath = ((HttpServletRequest) request).getContextPath();
String requestURI = httpRequest.getRequestURI();
modifiedRequest = new RequestWrapper(httpRequest, "/");
chain.doFilter(modifiedRequest, response);
}
class RequestWrapper extends HttpServletRequestWrapper {
private String originalValue;
public RequestWrapper(HttpServletRequest request) {
super(request);
}
#Override
public String getRequestURI() {
String originalURI = super.getRequestURI();
String s = super.getRequestURI();
if (StringUtils.equals(s, originalValue)) return originalValue
.replaceAll("client1", "");
else return s;
}
public RequestWrapper(HttpServletRequest request, String newValue) {
super(request);
this.originalValue = request.getRequestURI();
}
}
}
But all my tests failed. Can any one help me to resolve this ?
Thanks