Router primitives can be only used in side a Route.
I have a route that has a setup like this:
The auth page has a little form password popup, verifies the password , and saves a hash into a cookie, with the following pseudocode:
Once the right password is entered, the auth page action does a
return redirect(redirectUrl);
back to the original page... but then I get the attached error.
If I console log, I can see that it dies on the line where I have the const location = useLocation();
line in my getRouteData
function. If I manually refresh the page, it loads fine.
This worked fine in my initial build of the app prior to rc0 ๐25 Replies
This part
sounds like it should be done in
onRequest
in middleware. There you can stuff the result into in RequestEvent.locals or even return the redirect.
That way everything should be ready by the time it hits your "use server" section and you can obtain it via getRequestEvent.SolidStart Release Candidate Documentation
SolidStart Release Candidate Documentation
Early release documentation and resources for SolidStart Release Candidate
SolidStart Release Candidate Documentation
SolidStart Release Candidate Documentation
Early release documentation and resources for SolidStart Release Candidate
Unfortunately this example is a bit in a rough state (this was post Beta 2 but pre-RC) but it uses some of the concepts I was alluding to:
https://github.com/peerreynders/solid-start-demo-login/blob/restart/src/middleware.ts
If I were to clean it up now I'd be able to ditch the direct cookie manipulation and just use the h3 session api
GitHub
solid-start-demo-login/src/middleware.ts at restart ยท peerreynders/...
SolidStart seed project with simple user management for demonstration projects. - peerreynders/solid-start-demo-login
Handle Session - h3
Remember your users using a session.
Yeah, middleware could be a solution, but this setup is only needed for this one route.. and it was working fine until the upgrade to rc0. The fact that the initial Route A works fine unless it's coming from a redirect from another route is the main issue, middleware won't cure that unfortunately.
oooh, just looking at your example, I don't know of
sendRedirect
, is that a thing still?In middleware you have direct access to the URL, no
useLocation
required.Maybe I'm just redirecting incorrectly with this version.
Gotcha, will dive into the sample code, thanks ๐
Middleware can terminate the handler chain by returning, i.e. redirect.
Still wondering why useLocation works fine unless the page is loaded from a redirect though.... router magic.
Full disclosure: nitro recommends against prematurely terminating the handler chain but they are not clear on why
https://nitro.unjs.io/guide/routing#simple-middleware
Server Routes - Nitro
Nitro support filesystem routing to automatically map files to h3 routes.
urgg, always something. What could go wrong? ๐
I just think it's philosophical and judged as harder to maintain.
But in the face of streaming SSR middleware is the best place to manipulate cookies and return redirects.
Claude ai says "The reason why it is not recommended to use the returned value from middleware as the response in Nitro (or any other middleware-based system) is that it can lead to potential issues and can make the code more difficult to maintain and understand.
In a typical middleware system, the middleware functions are intended to perform specific tasks or operations before or after the main request handling logic. These tasks can include authentication, logging, parsing request data, modifying the request or response objects, and so on. The middleware functions are not meant to directly handle the main request or generate the final response.
When you return a value from a middleware function, it essentially short-circuits the request pipeline, and the remaining middleware functions and the main request handler will not be executed. This can lead to several problems:"
"Violation of Separation of Concerns: By allowing middleware to generate the final response, you are mixing concerns and responsibilities. Middleware functions should focus on their specific tasks, while the main request handler should be responsible for generating the response.
Difficulty in Maintaining and Understanding the Flow: If middleware functions can generate responses, it becomes harder to understand the flow of the application and the order in which different parts of the code are executed. This can make the codebase more difficult to maintain and debug.
Potential for Inconsistent Behavior: If multiple middleware functions can generate responses, it can lead to inconsistent behavior and unexpected outcomes, especially if there are dependencies between middleware functions or if they rely on certain data or state that may not be properly set up due to short-circuiting.
Lack of Centralized Error Handling: When middleware functions generate responses, it becomes harder to implement centralized error handling and response formatting, as errors and responses may be generated at different points in the request pipeline.
Instead of returning a response from middleware, it is recommended to follow the intended pattern of middleware systems, which is to perform specific tasks within the middleware functions and then pass control to the next middleware or the main request handler. This approach promotes better separation of concerns, maintainability, and a more predictable flow of execution.
If you need to generate a response early in the request pipeline (e.g., for authentication failures, rate limiting, or other early-exit scenarios), it is generally better to use the provided mechanisms within the middleware system, such as calling a dedicated response generation function or throwing an error that can be caught and handled by a centralized error handler."
So yeah, more for maintenance and behavior than anything technical
unless the page is loaded from a redirect thoughtI suspect the route preload is creating a race condition.
useLocation
only works once the Router component is "fully informed" and likely the cache point is being hit before that is the case.
Pure conjecture at this point though โฆbut a great idea, and something to look into...
nope ๐ Removed
cache()
altogether and still get the same thing.This comment makes me think we are going to see more "best practices" about moving functionality into middleware going forward.
https://github.com/nksaraf/vinxi/issues/208#issuecomment-1964625870
GitHub
Error: Cannot set headers after they are sent to the client ยท Issue...
It seems it's not possible to set the session at present in my solid-start project. All request are returning: Error: Cannot set headers after they are sent to the client at ServerResponse.setH...
I was thinking the preload is the problem
in the page that dies, I am deferring it via
const routeData = createAsync(() => getRouteData(), { deferStream: true });
So I was assuming it'd 'wait'.That just defers the response during SSR.
right, but doesn't that halt everything until the server code is all executed/finalized?
Regardless, it looks like I need to do some middleware for this one route.
That wouldn't resolve any timing issues "at the front "
yeah
next question is how can I only run middleware for 1 route block? i.e. I've got 100 routes, but only need it to run on this block of 3 which are nested in a
ViewersRoute
component .
docs look like it's only a global thing, and I don't really want to do a url path check for every single request?You simply look at the relevant part of the URL. If there is nothing to do you let it go.
right, that's what I was worried about. Okay, url path check for every single request it is.
That's negligible, don't worry about it.
https://refactoring.guru/design-patterns/chain-of-responsibility
Chain of Responsibility
Chain of Responsibility is a behavioral design pattern that lets you pass requests along a chain of handlers. Upon receiving a request, each handler decides either to process the request or to pass it to the next handler in the chain.
vinxi/http
still re-exports (and wraps) sendRedirect
https://h3.unjs.io/utils/response#sendredirectevent-location-codeGitHub
vinxi/packages/vinxi/runtime/http.js at 6f3d81beabc8cf003c0095eb9b4...
The Full Stack JavaScript SDK. Contribute to nksaraf/vinxi development by creating an account on GitHub.
Response - h3
Utilities to send response headers and data
Sooo, the actual issue was that on the redirect from Component B back to Component A, the routeData function is called using an internal
_server
url, which didn't have access to use useLocation().
I also found getRequestEvent();
, so I was able to find out what caused the issue with useLocation(), but also able to get rid of useLocation() ๐