Skip to content

HttpServletResponse#sendRedirect(String) could use some improvement; needs 301/302/303 support; needs way to set request body #74

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
glassfishrobot opened this issue May 25, 2013 · 7 comments
Labels
Enhancement New feature or request

Comments

@glassfishrobot
Copy link

Currently, HttpServletResponse#sendRedirect(String) specifies the following hard-wired behavior that cannot be changed:

  • Send the redirect using status code 302 Found and the Location header.
  • Clear the buffer and set the response body to a short hypertext note with a hyperlink to the new URI.

I have three issues with this behavior that I summarize below, and at the bottom I propose a solution:

Issue 1

RFC 2616, says the following about 302 Found:

If the 302 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

Note: RFC 1945 and RFC 2068 specify that the client is not allowed to change the method on the redirected request. However, most existing user agent implementations treat 302 as if it were a 303 response, performing a GET on the Location field-value regardless of the original request method.

The two keys here are 1) that the spec says browsers MUST NOT automatically redirect the request and 2) that there could be some browsers that send the second request with the original method (POST, PUT, etc.).

As an application not concerned with legacy HTTP/1.0 user-agents and more concerned with ensuring that user agents do not prompt the user for permission to redirect and do not redirect using a POST or a PUT, etc., I prefer to use the 303 See Other response as opposed to the 302 Found response:

The response to the request can be found under a different URI and SHOULD be retrieved using a GET method on that resource. This method exists primarily to allow the output of a POST-activated script to redirect the user agent to a selected resource. ... The 303 response MUST NOT be cached, but the response to the second (redirected) request might be cacheable.

Issue 2

As an application that has recently been refactored, I want to be able to easily send a permanent redirect to users for old URLs that have been removed and should be changed. This can be achieved with the 301 Moved Permanently response:

The requested resource has been assigned a new permanent URI and any future references to this resource SHOULD use one of the returned URIs. Clients with link editing capabilities ought to automatically re-link references to the Request-URI to one or more of the new references returned by the server, where possible. ... The new permanent URI SHOULD be given by the Location field in the response. Unless the request method was HEAD, the entity of the response SHOULD contain a short hypertext note with a hyperlink to the new URI(s). ... If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.

Issue 3

The exact wording of the short hypertext response included with the current 302 Found responses is not consistent across containers. As an application developer that cares about branding and consistency, I would like to be able to customize this text within my code and do so in a way that is consistent across all containers.

Recommendation

I believe the following additions to the Servlet API will greatly improve the current HttpServletResponse#sendRedirect(String) and satisfy the needs outlined here.

**New HttpRedirectType Enum**public enum HttpRedirectType {
    /*
     * Indicates that the {@code 301 Moved Permanently} status should be used.
     * Could alternatively be called MOVED_PERMANENTLY.
     */
    PERMANENT,

    /*
     * Indicates that the {@code 302 Found} status should be used.
     * Could alternatively be called FOUND.
     */
    TEMPORARY_SAME_METHOD,

    /*
     * Indicates that the {@code 303 See Other} status should be used.
     * Could alternatively be called SEE_OTHER.
     */
    TEMPORARY_USE_GET;
}
**Additions to HttpServletResponse**public interface HttpServletResponse {
...
    void sendRedirect(String location, HttpRedirectType type);

    void sendRedirect(String location, boolean replaceBuffer);

    void sendRedirect(String location, HttpRedirectType type, boolean replaceBuffer);
...
}
  • If replaceBuffer is true, the container should clear the buffer and replace it with the data set by this method. If replaceBuffer is false, the container should send the existing buffer and should not add to it (even if it is empty) or remove from it.
  • The existing sendRedirect(String) should call sendRedirect(location, HttpRedirectType.TEMPORARY_SAME_METHOD, true) to preserve current behavior.
  • The new sendRedirect(String, HttpRedirectType) should call sendRedirect(location, type, true) to use the default response body.
  • The new sendRedirect(String, boolean) should call sendRedirect(location, HttpRedirectType.TEMPORARY_SAME_METHOD, replaceBuffer) to use the default 302 Found response.
@glassfishrobot
Copy link
Author

@glassfishrobot Commented
Reported by beamerblvd

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
Issue-Links:
is related to
SERVLET_SPEC-100

@glassfishrobot
Copy link
Author

@glassfishrobot Commented
This issue was imported from java.net JIRA SERVLET_SPEC-74

@glassfishrobot
Copy link
Author

@gregw gregw added Enhancement New feature or request and removed 301 labels Jan 18, 2020
markt-asf added a commit to markt-asf/servlet-api that referenced this issue Feb 21, 2023
markt-asf added a commit to markt-asf/servlet-api that referenced this issue Mar 2, 2023
@pmd1nh
Copy link

pmd1nh commented Mar 25, 2024

Hi @markt-asf

For sendRedirect(String, int) or sendRedirect(String, int, boolean), should the API or doc specify what to do if the user use arbitrary status code other than 301, 302, or 303? Should the default 302 be used for that case?

@joakime
Copy link

joakime commented Mar 26, 2024

For sendRedirect(String, int) or sendRedirect(String, int, boolean), should the API or doc specify what to do if the user use arbitrary status code other than 301, 302, or 303? Should the default 302 be used for that case?

The use of sendRedirect(String, int) or sendRedirect(String, int, boolean) does three things.

  • Adds a resolved Location response header
  • Sets the status code given
  • Commits the response.

The existence of a Location response header is used for HTTP response status codes 201 (Created) and all of the 3xx range.
If the Location response header shows up in any other status code it has no meaning, and is not even looked at.

There's no reason to limit the status codes to just 301, 302, or 303.
You can easily use sendRedirect("/what/do/you/know", 200) and that would be valid to HTTP.
You would get a 200 response status code, a Location: /what/do/you/know response header, and no body (a Content-Length: 0 likely too).

@markt-asf
Copy link
Contributor

+1
While I don't see any reason an application would want to do that, I also don't see any reason to limit it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants