express icon indicating copy to clipboard operation
express copied to clipboard

HTML in the `res.redirect()` method is missing a `DOCTYPE` and `<title>` element

Open SaekiTominaga opened this issue 3 years ago • 4 comments

The response body of a redirect via the res.redirect() method will be <p>${statuses.message[status]} Redirecting to <a href="${url}">${url}</a></p>, which is invalid HTML without a DOCTYPE and <title> element. In particular, the absence of a <title> element is detrimental to the user.

RFC 9110, 15.4. Redirection 3xx, states that the user agent behavior when the Location header field is set with status code 3xx is "the user agent MAY automatically redirect its request to the URI". Note that it is MAY.

And in fact, depending on the user's environment, automatic redirection may not occur and the contents of the response body may be displayed on the screen. In the old days, there was an option to disable redirects in Presto Opera's advanced settings. Even now, when Android Firefox redirects to an app-linked URL with 3xx, the app is automatically launched, but the browser screen still displays the 3xx response body.

Therefore, it would be desirable to set the DOCTYPE and <title> element even for 3xx screens.

Improvement plan

https://github.com/expressjs/express/blob/8368dc178af16b91b576c4c1d135f701a0007e5d/lib/response.js#L963

body = '<!DOCTYPE html><title>' + statuses.message[status] + '</title><p>' + statuses.message[status] + '. Redirecting to <a href="' + u + '">' + u + '</a></p>'

SaekiTominaga avatar Dec 08 '22 02:12 SaekiTominaga

Not sure that this is something standard. What is being done by others frameworks / languages? If needed - we should provide a complete and valid HTML part (which would include header/body) - but again this is a nice to have as the RFC doesn't precise that we need to send a value.

sheplu avatar Dec 14 '22 20:12 sheplu

I am not familiar with the status of other Node.js frameworks, but the situation of popular web server software is as follows.

Apache 2.4

ServerSignature Off
Redirect permanent / https://example.com/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://example.com/">here</a>.</p>
</body></html>

nginx 1.23

location / {
    rewrite ^ https://example.com/ permanent;
}
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.23.3</center>
</body>
</html>

SaekiTominaga avatar Dec 15 '22 08:12 SaekiTominaga

Hi @SaekiTominaga thank you for that! Those seem to have a lot more parts than your initial recommendation.

So in order to understand the issue, can you provide us the details of what clients are not able to render the response from express? This will better help guide the conversation by having the information regarding which clients/browsers are having an issue with the response from Express and thus we can work to make sure and validate that any changes made will resolve the issue.

dougwilson avatar Dec 15 '22 08:12 dougwilson

Hi, @dougwilson !

Currently, most browsers automatically redirect when a Location header is present in a 3xx, so the user has very limited exposure to the response HTML. As noted in the first comment, I know this occurs in Android Firefox.

  1. Install Firefox and the Twitter application on Android device.
  2. Put the redirection process in app.js. (Code#1)
  3. Access http://localhost:3000/twitter with Firefox.
  4. The Twitter application will automatically launch.
  5. When you return to the Firefox application, the redirect screen will be displayed. (Image#2)
  6. Here, the <title> element is not present, so the tab displays the URL as is. If <title> element is set, the tab will display its value. (Image#3)

Code#1 (app.js)

app.get('/twitter', (req, res) => {
	res.redirect(301, 'https://twitter.com/');
});

Image#2 Redirect message is displayed on the browser screen

Image#3 A side-by-side view of the redirect screen and Google page in a browser

* The redirect process itself works fine. This is just a measure to prevent user confusion by displaying the page title in the browser tab by adding the <title> element. * According to the HTML specification, the <title> element is required, with a few exceptions. Therefore, regardless of how Android Firefox works, even redirect screens should include a <title> element.

SaekiTominaga avatar Dec 15 '22 09:12 SaekiTominaga