Reputation: 771
A Spring MVC controller needs to redirect the control flow of an app to a different url endpoint within the same app. But the current code is returning a blank page along with response
headers
that include the intended destination url as the forward
header. When the contents of the forward
header is pasted into the web browser, the intended endpoint is successfully called. What specific changes need to be made to the code below in order for the POST
controller to successfully redirect the control flow to the intended destination endpoint instead of returning a blank page?
Here is the code for the Controller method:
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public ResponseEntity<?> auth(FormData formData, HttpServletRequest req, HttpServletResponse resp) {
System.out.println("11111111111111 inside POST");
HttpHeaders responseHeaders = new HttpHeaders();
boolean passedTheTest = true;//ACTUAL LOGIC IS OMITTED HERE FOR SIMPLICITY
if (passedTheTest) {
//SOME OFF TOPIC LOGIC HERE IS OMITTED
CsrfToken csrf = (CsrfToken) req.getAttribute(CsrfToken.class.getName());
String updateCsrf = csrf.getToken();
responseHeaders.set("XSRF-TOKEN", updateCsrf);
if(resp.getHeaders("Cache-Control")!=null){responseHeaders.put("Cache-Control" , new ArrayList<String>(resp.getHeaders("Cache-Control")));}
if(resp.getHeader("Content-Language")!=null){responseHeaders.set("Content-Language" , resp.getHeader("Content-Language"));}
if(resp.getHeader("Content-Length")!=null){responseHeaders.set("Content-Length" , resp.getHeader("Content-Length"));}
if(resp.getHeader("Date")!=null){responseHeaders.set("Date" , resp.getHeader("Date"));}
if(resp.getHeader("Expires")!=null){responseHeaders.set("Expires" , resp.getHeader("Expires"));}
if(resp.getHeader("Pragma")!=null){responseHeaders.set("Pragma" , resp.getHeader("Pragma"));}
if(resp.getHeader("Server")!=null){responseHeaders.set("Server" , resp.getHeader("Server"));}
if(resp.getHeader("X-Application-Context")!=null){responseHeaders.set("X-Application-Context" , resp.getHeader("X-Application-Context"));}
if(resp.getHeader("X-Frame-Options")!=null){responseHeaders.set("X-Frame-Options" , resp.getHeader("X-Frame-Options"));}
if(resp.getHeader("X-XSS-Protection")!=null){responseHeaders.set("X-XSS-Protection" , resp.getHeader("X-XSS-Protection"));}
if(resp.getHeader("x-content-type-options")!=null){responseHeaders.set("x-content-type-options" , resp.getHeader("x-content-type-options"));}
if(req.getSession().getAttribute("forwardTo")!=null){
String redirectTo = getValidUriFromAnotherFunction();
try {
URI location = new URI(redirectTo);
responseHeaders.setLocation(location);
} catch (URISyntaxException e) {e.printStackTrace();}
ResponseEntity<Void> forwardResponseEntity = new ResponseEntity<Void>(responseHeaders, HttpStatus.CREATED);
return forwardResponseEntity;
}
};
return new ResponseEntity<String>("aDifferentViewTemplateName", responseHeaders, HttpStatus.CREATED);
}
The request
headers
in the browser's developer tools are:
Host: localhost:7777
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:7777/path/to/controller_method
Cookie: JSESSIONID=911B34457B69F7729091DD97A160AD79; JSESSIONID=95AA730306330CF15E3776C495807354; XSRF-TOKEN=04ae2a0c-3c58-4e85-88bd-3818bb10402a
Connection: keep-alive
The response
headers
for the same POST
are:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate, no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Sun, 29 May 2016 21:48:24 GMT
Expires: 0, 0
Location: http://localhost:7777/path/to/forward_destination?long_querystring
Pragma: no-cache, no-cache
Server: Apache-Coyote/1.1
X-Application-Context: application:7777, application:7777
X-Content-Type-Options: nosniff, nosniff
X-Frame-Options: DENY, DENY
X-XSS-Protection: 1; mode=block, 1; mode=block
XSRF-TOKEN: 04ae2a0c-3c58-4e85-88bd-3818bb10402a
The Spring Boot debug log for the same POST
includes three sections, which have been separated as follows for improved readability:
Section of debug log that shows the SYSO inside the controller:
11111111111111 inside POST
redirectTo is: http://localhost:7777/path/to/forward_destination?long_querystring
Section of debug log AFTER the controller (most important?):
2016-05-29 14:48:24.489 DEBUG 5533 --- [io-7777-exec-10] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2016-05-29 14:48:24.489 DEBUG 5533 --- [io-7777-exec-10] w.c.HttpSessionSecurityContextRepository : SecurityContext 'org.springframework.security.core.context.SecurityContextImpl@42259e42: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@42259e42: Principal: org.springframework.security.core.userdetails.User@40fecce: Username: SomeUser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ONE,ROLE_TWO; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@fffe3f86: RemoteIpAddress: 127.0.0.1; SessionId: 02A95844E8A829868542290D471503F5; Granted Authorities: ROLE_ONE, ROLE_TWO, ROLE_THREE' stored to HttpSession: 'org.apache.catalina.session.StandardSessionFacade@64307ead
2016-05-29 14:48:24.489 DEBUG 5533 --- [io-7777-exec-10] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
Upvotes: 3
Views: 5319
Reputation: 66
Instead of returning the 201 Created status code you should return a 3XX status code to ask the user agent to load a different web page. Otherwise the Location header has no "special" meaning.
So for example you can write:
ResponseEntity<Void> forwardResponseEntity = new ResponseEntity<Void>(responseHeaders, HttpStatus.MOVED_PERMANENTLY);
Upvotes: 5