-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
feat(node): add trailingSlash support #9080
Conversation
🦋 Changeset detectedLatest commit: 9f21d46 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for the PR! This is great work but I'm not sure if it's implemented at the correct layer. I think this might make more sense implemented in the Middleware itself? @matthewp might have the most context here.
handler: http.RequestListener, | ||
trailingSlash: AstroUserConfig['trailingSlash'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that createServer
is the right place to handle this... Seems like we should be able to read the trailingSlash
value from the manifest and use that to point requests to the correct route.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah sounds right. What I'm unsure about is why this needs to happen in the adapter level and not inside of Astro core itself. It seems like we should be handling trailingSlash ourselves. I can't recall why we do not.
It might be the case that we forgot to initially, and thought it would be backwards incompatible to do so. I do have some recollection of handle trailing slash for things like assets at build time (by making sure it was correct in the manifest).
If that's the case, then I thinking having in the Node adapter is ok, and if we ever fix it in core then it will just already be fixed before it gets there.
In any case, fixing it inside of the middleware seems ideal.
@@ -15,6 +16,7 @@ export interface Options extends UserOptions { | |||
port: number; | |||
server: string; | |||
client: string; | |||
trailingSlash: AstroUserConfig['trailingSlash']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should change the signature of the Node options. This information is already available in the Astro config, so it should be available to the app
that is generated by Astro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, agree here
I wonder if this behaviour should be implemented inside |
matthewp confirmed that what ematipico suggested is the way to do. Would you be willing to resolve conflicts and make the changes required @msxdan? |
Sure, I'll review it and make the changes suggested |
@matthewp @ematipico I'm unsure this can be handled inside the Should we call the handler for each request? that way it will call the match function everytime, however I'm not sure that will work fine, the standalone mode is serving the content by itself unless there's an error |
@msxdan I'm not sure I understand, that stream code is about serving files. It checks if there's a file and if not, it calls the SSR handler. But I'm not sure what this has to do with trailingSlash. Aren't we already calling into astro/app for the trailing slash, but astro/app is just not handling it? |
@matthewp The astro/app was not called by default before serving the file, only when there's no existing file, I cannot add the trailingSlash logic inside If you can tell me some suggestions about how it should work I could try to implement it. |
@msxdan That's how it's supposed to work, it checks for files first, and if no files exist, it then calls Astro to render. Are you expecting Astro render to take precedent over files? |
This comment was marked as outdated.
This comment was marked as outdated.
@msxdan are you still interested in this PR? |
Yes I am, sorry I've been busy all these days |
@matthewp about our last conversation The static files are served from the http-server and we have no context about the manifest and hence the trailingSlash, that's why I added the trailingSlash inside Options I tried to use the render function inside the astro core but it is unable to render static files or I don't know how it works, so since the App or NodeApp has the trailingSlash info I don't know how to implement it inside the http-server, and the nodeMidleware cannot render the files so I'm a bit stuck |
@msxdan Let's use an example to talk through. Let's say you have these files:
If page renders were prioritized then it would be impossible to ever get the image at If you'd like to change this to make files be checked last, we can talk about doing that through a new option perhaps, but that's different from getting trailingSlash to work. Could create a reproduction with astro.new that shows |
detected an infinite loop in base path when trailingSlash: never
if (urlQuery && !pathname.includes('?')) { | ||
pathname = pathname + '?' + urlQuery; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on this line?
If we add the query right before send
handles the pathname, wouldn't it prevent send
from matching files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@msxdan I would be ready to approve after clarification on this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lilnasy I'm not sure but I guess if it was failing the tests wouldn't be passing, isn't it?, I think the query data should be included in the pathname since if you do a redirect without it you'll lose the query data
with trailingSlash: always
domain.com/test?name=astro -> 301
domain.com/test/?name=astro
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After my rebase, it was failing the tests with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point. I hadn't thought of it, but that's behavior I would want as well.
In the code, I see that the query data is added to the path right before performing a redirect. I see that you had written tests for it as well.
So, it looks good to me if it looks good to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checked, looks good to me as well!
0a69da8
to
55f0468
Compare
The node adapter just had a major overhaul. I have rebased this PR on top of the changes introduced. Original commits:
|
55f0468
to
9f21d46
Compare
!preview node-trailing-slash |
Snapshots have been released for the following packages:
Publish Log
Build Log
|
I did some testing:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me! Thanks for the clean fix and thorough tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to merge too. After more testing, I could see things working as expected
Changes
ignore
,always
andnever
values with nodejs adapterTesting
Add tests to use each possible value of trailingSlash and check if expected results are good and not breaking other tests
trailingSlash = always
→ Should always contain the / at the end (will always return host/pathname/?queryifexists)trailingSlash = never
→ Should never contain the / at the end (will always return host/pathname?queryifexists)trailingSlash = ignore
→ Should ignore the / at the end (will always work without redirect)New behaviour of
trailingSlash = ignore
will return 200 and the content of the index.html inside the directoryDocs
Should work as expected in current documentation
I know there's currently an open PR (#8593) about this, but I was not able to make it working and needed this for a personal project