具有HTTP Location头的ResponseEntity不会导致重定向

时间:2016-05-29 22:21:42

标签: java spring http spring-mvc spring-boot

Spring MVC控制器需要将应用程序的控制流重定向到同一应用程序中的不同url端点。但是,当前代码返回一个空白页面以及response headers,其中包含预期的目标网址作为forward标头。将forward标头的内容粘贴到Web浏览器中时,将成功调用目标端点。 为了使POST控制器成功地将控制流重定向到目标目标端点而不是返回空白页,需要对下面的代码进行哪些具体更改?

以下是Controller方法的代码:

@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);
}

浏览器开发者工具中的request headers为:

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

相同response的{​​{1}} headers为:

POST

同一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 的Spring Boot调试日志包括三个部分,这些部分已按如下方式分隔,以提高可读性:

显示控制器内SYSO的调试日志部分:

POST

调试日志部分在控制器之后(最重要的?):

11111111111111 inside POST
redirectTo is: http://localhost:7777/path/to/forward_destination?long_querystring

1 个答案:

答案 0 :(得分:1)

您应该返回3XX状态代码,要求用户代理加载不同的网页,而不是返回201 Created状态代码。否则,Location标头没有&#34; special&#34;含义。

例如,你可以写:

ResponseEntity<Void> forwardResponseEntity = new ResponseEntity<Void>(responseHeaders, HttpStatus.MOVED_PERMANENTLY);