Replies: 8 comments 16 replies
-
Great explanation! |
Beta Was this translation helpful? Give feedback.
-
I'm cool with that. I guess you'd probably need to state that as a big breaking change ? Btw #300 is about moving all config to the new radix router |
Beta Was this translation helpful? Give feedback.
-
Thanks @vejja for a great write up. I will take a look at it next week as I want to give you a good comments and I didn't have much time this week :( |
Beta Was this translation helpful? Give feedback.
-
Another thing that comes to my mind is co-existence of header configuration via module options and via nitro plugin route rules. A Nuxt layer might set headers via module options and your project via a nitro plugin, just to give an example. In my testing of #298 only the module options are kept, the route rules are not merged in. But maybe that's by design already? cc @Baroshem |
Beta Was this translation helpful? Give feedback.
-
Sorry @dargmuesli I’m not sure I fully understand |
Beta Was this translation helpful? Give feedback.
-
I'm currently thinking about the object structure of I'd thus vote to keep the OptionKey syntax for the |
Beta Was this translation helpful? Give feedback.
-
Hey guys, I finally had some time to take a look at this discussion. First of all, thanks for the great comments! 🚀 I will share my thougts below but in general, I think such change can occur no earlier than for 2.0.0 release due to potential breaking changes that I prefer to avoid as much as possible (especially because we recently released a stable 1.0.0). Are you ok with that? |
Beta Was this translation helpful? Give feedback.
-
Hi @huang-julien I've got one question for you, which relates to the tests you added into tests/runtime-hooks. BTW if you want to check the WIP implementation you can have a look at the feat/unified-runtime-context branch |
Beta Was this translation helpful? Give feedback.
-
Outline
This module modifies the HTTP headers, most importantly the
Content-Security-Policy
header.This discussion is a forum to think about a potential refactoring of the way we modify headers.
Challenges
We have 3 main challenges today
1. About potential conflicts
Headers can be defined in 2 locations:
routeRules.headers
: this is a standard feature of Nuxt (aka in my language, the Standard Headers)routeRules.security.headers
: this is a custom feature of Nuxt-Security (aka the Security Headers)2. About syntax
The syntax is not the same:
"Content-Security-Policy": "script-src: self;"
for Nuxt (aka the HeaderName syntax)contentSecurityPolicy: { "script-src": ['self'] }
for Nuxt-Security (aka the OptionKey syntax)3. About asset types
Nuxt-Security modifies the headers only for HTML ressources (i.e. all
*.vue
pages which are rendered to the user).It does not modify the headers for server routes (
/api/...
) or for static assets (all*.js
scripts, allcss
files, images, etc.)Current architecture
1. How we resolve the potential conflicts
A basic example of conflict is when the user defines a
Content-Security-Policy
in both places.This is easy to resolve because we apply a simple principle: Nuxt Security has priority
But the potential conflicts between Nuxt headers and Nuxt-Security headers can be much more complex.
This is because
routeRules
are the rules for a router, which can contain wildcards and sub-routes.So if there are conflicts for
/**
and conflicts for/special
, the resolution of conflicts will not be the same if the request is for/foobar
or for/special
.In short, because route pattern possibilities are infinite, it is not possible to resolve all conflicts in advance at build time.
The way we solve this is by letting Nuxt resolve the conflict at runtime until the last moment, i.e. when the request arrives.
What happens under the hood are the following steps :
1- When the request is processed, Nuxt has already calculated the Standard Headers in the
event.headers
2- We extract the Security Headers via
{ security } = getRouteRules(event)
3- We apply the principle that Nuxt Security has priority by overwriting
event.headers
4- We let the Nuxt process continue with the modified
event.headers
With this approach, we have correct conflict resolution for both
/foobar
and/special
.2. On the syntax differences
This is not a huge problem. We have a set of utilities in
/src/utils/headers
that convert one syntax to the other.3. On the type of assets
The Nuxt-Security headers are only applied to HTML resources because we use a Nitro plugin that hooks into
render:html
.If we were using a Nuxt Server Middleware plugin, it would be applied to all requests.
So what happens here is that
/api
route or to a static asset (.js, .css, etc...), our Nitro plugin is not invoked. In that case, only the Standard Headers defined inrouteRules
are delivered to the userPotential for improvement
PR #298 introduces the ability to configure headers at runtime.
The way it is implemented is by doing 2 things
event.context.security
objectrouter
instanceWe end up in a situation where we have 2
unjs/radix3
router instances.My intuition is that using the new router created by PR #298 is better than using the standard router.
A potential refactoring would be
{ security }
object to the standard Nuxt router (we don't know whether this will be supported in the future)getRouteRules()
in the standard Nuxt routerevent.context.security
objectNext Steps
This is basically an architecture discussion.
I would be happy to get the feedback of @huang-julien and @Baroshem on whether they think this is feasible
Cheers !
Beta Was this translation helpful? Give feedback.
All reactions