Default trailingSlash config breaks relative links
Relative href attributes are not correctly resolved based on the configuration of cleanUrls and trailingSlash config.
Scenario
Files:
-
/login/index.html -
/login/login.ts.html
The index.html has an anchor tag linking to the other page like following:
<a href="login.ts.html">login.ts</a>
(Something like this could be found in an instanbul coverage html report)
This looks to me like a correct link that should correctly link from index.html to login.ts.html.
Observed behavior
- Start
serve - Open browser on localhost:5000/login/index.html
- The server responds with 301:
Location | /login/index(this must be the result of thecleanUrlssetting removing the file ending .html) - The browser follows the redirect and requests localhost:5000/login/index.html
- The server responds again with 301, now for:
Location | /login(is this also part of thecleanUrlssetting? but anyway, settingtrailingSlashto false changes the target/login/) - The browser requests localhost:5000/login and gets a result that is rendered
- The browser resolves the relative URL "login.ts.html" as a sibling of "/login" and goes to localhost:5000/login.ts.html
- Serve can not serve the file because this path does not exist.
Expected behavior
Serve should (by default) be configured, so that requesting localhost:5000/login/index.html should settle on one of the following URLs to not break relative URL resolution:
- localhost:5000/login/index.html
- localhost:5000/login/index
- localhost:5000/login/
I am aware that i can configure my serve.json to disable trailingSlash. This solves my problem locally but i am arguing for making sure that the default configuration should be changed.
Just wanted to confirm that I've run into similar.
Looks like serve can't tell the difference between a subpath and a filename that it's stripped the extension from.
Short of broken user-supplied rewrite rules, it's very incorrect for correctly-supplied paths in an HTML to 404, and it's frustrating that this breakage is caused by gold plating.
AFAICT, it's conventional for web servers to add a trailing slash when removing "index.html" from a URL (which keeps relative links within subpaths intact) but not to do the other things serve attempts.
Thank you to @lukengda for explaining & providing a workaround... I thought I was going crazy, and even switched a static-page project to all absolute paths because I didn't realize the problem was serve.
Ok, apparently this issue has already been raised a few other times, over a period of years. A couple others:
- https://github.com/vercel/serve-handler/issues/79
- https://github.com/vercel/serve/issues/441
But what I did as a workaround (because I still prefer serve to simplehttpserver): Create a serve.json with
{
"trailingSlash": true
}
Then I put that in my home folder, and aliased serve as serve='serve -c ~/serve.json'.
Edit: the right trailingSlash setting actually depends on what you're trying to serve. For foo/index.html you want it on, but for foo.html you want it off. 🙄
Here's a better workaround:
$ python -m SimpleHTTPServer 5000
I'm encountering the same issue. I have a directory like:
index.html
docs
index.html
images
image1.png
image2.png
...
The docs/index.html contains references to images/image1.png. When I open a link to docs/index.html from the main application index.html, it is redirected to docs, and then the relative urls to the images are broken.