Skip to content
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

Intercept network resource requests / defining resource loader #1502

Closed
SebJansen opened this issue Aug 7, 2024 · 19 comments
Closed

Intercept network resource requests / defining resource loader #1502

SebJansen opened this issue Aug 7, 2024 · 19 comments
Labels
enhancement New feature or request

Comments

@SebJansen
Copy link

SebJansen commented Aug 7, 2024

Is your feature request related to a problem? Please describe.
JSDOM has the ability to define custom resource loaders, to avoid the need for network requests, by going through the filesystem instead. This saves precious milliseconds.

JSDOM resource loaders also have access to the requesting HTML element; eg if a style element is requesting a CSS file, the loader can get it from the filesystem instead and then replace the element with a <style> element with the CSS inlined to prevent the client needing to make an additional network request for the CSS file upon first page being served.

Describe the solution you'd like
Some way to intercept network requests and instead serve them from the filesystem. Perhaps this is already possible with HappyDOM but merely undocumented.

Describe alternatives you've considered
Overriding window.fetch requires some properties like browser frame, which are not exposed during eg new Window(). Perhaps with a little guidance it is possible to document a way to override fetch.

@SebJansen SebJansen added the enhancement New feature or request label Aug 7, 2024
@Doeke
Copy link

Doeke commented Aug 12, 2024

I've also just run into this issue, the code I need to test at some point adds a <link> tag to load a webfont which results in AbortErrors (in Fetch.onAsyncTaskManagerAbort) while running tests.

Edit: All I have found is the setting disableCSSFileLoading, but no way to intercept or mock it. This setting also annoyingly still prints errors to stdout (NotSupportedError) every time a CSS file is requested

@mariusrak
Copy link

Hi, i also very much need this. I do requests only inside my own server and do not need to go through network. So this intercepting fetch request would greatly increase performance and security.

@OlaviSau
Copy link
Contributor

Hi :) We also would greatly appreciate this, again currently using patch-package to get around this.

@OlaviSau
Copy link
Contributor

#1556 Just an example of something that could work.

@SebJansen
Copy link
Author

SebJansen commented Sep 27, 2024

Maybe it's simpler to build this feature if we see it as overriding (some part of) Happy's caching behavior, that is executed in addition to preexisting behavior, only if this 'Cache 'Interceptor' is defined during initialization

@SebJansen
Copy link
Author

#1556 Just an example of something that could work.

Looks like a clean and simple solution! :)

I hope capricorn86 see this so that he can steer us into a certain direction

There's the happy-dom-without-node package that might be polluted if we go a little crazy here with nodejs specific code

@OlaviSau
Copy link
Contributor

@SebJansen I discussed it with a colleague and although file urls would work, the caching would be a bit tricky as files can change at any moment. It is probably wiser to implement a full interceptor instead.

@capricorn86
Copy link
Owner

Hi! 👋
I agree that something is needed, but I'm not sure what the best solution would be yet 😅 Another feature I would like is to make it possible to simulate a local web-server that is served from a "public" directory. It should also be easy to add transformers for resources loaded.

If you feel that this should be prioritized, I recommend adding a 👍 to the ticket. There are a lot of feature requests to sort between and the thumb indicate that several has voted for it.

@mariusrak
Copy link

Hi, I'm trying to replace JSDOM with happy-dom. I think, JSDOM solves this problem just right. You can define ResourceLoader in options an provide a class that implements fetch() method it should return Buffer with result. It would be nice if it would process not only buffer but also http.response, but that's just minor detail. Anyways, this mechanism works great for me, I implement custom simulation of a local server as you mention and it works together very well. What do you think about this approach?

@capricorn86
Copy link
Owner

@mariusrak I will have to look into it in more detail. I think that the downside of using a class is that it is not very declarative. It could be nice to be able to send in some settings with the rules. Perhaps both and easy and an advanced option can be supported.

@mariusrak
Copy link

@capricorn86 there are some stuff you cannot achieve by declarative approach and rules. I'm using JSDOM inside worker, I need to send custom message to main thread on fetch. Even if you made some config options for this particular case, somebody will for sure come up with something that is not implemented. Can we go for start with the imperative way and maybe later introduce some declarative API?

@OlaviSau
Copy link
Contributor

@capricorn86 We also use happy-dom inside an worker and the interceptor (implemented using patch-package) is used to provide assets directly from the file system. To me - an user defined interceptor seems to be the best solution as only the user knows when the files are supposed to update, doing that with a declarative approach is hard to imagine, but I am looking forward to seeing / hearing your ideas :)

@SebJansen
Copy link
Author

@capricorn86 We also use happy-dom inside an worker and the interceptor (implemented using patch-package) is used to provide assets directly from the file system. To me - an user defined interceptor seems to be the best solution as only the user knows when the files are supposed to update, doing that with a declarative approach is hard to imagine, but I am looking forward to seeing / hearing your ideas :)

Agreed. I think something as trivial as authorization often requires complicated and special logic that is more suitable to an imperative flow.

@mariusrak
Copy link

Hi, any info or news on this? Looks like many people need this. For me it seems like huge problem, since it hinders performance greatly. Thanks.

@mariusrak
Copy link

So this situation just broke my SSR. I have GTM in code (which, okay is incorrect to have in SSR) and I got error

DOMException: Failed to perform request to "https://www.googletagmanager.com/gtm.js?id=...%3Em_auth=%3Em_preview=%3Em_cookies_win=x". Status 404 Not Found.

And it simply crashed my SSR.
So, please, provide more options for handling fetches of external resources.

@OlaviSau
Copy link
Contributor

OlaviSau commented Jan 3, 2025

I have created a PR proposal for this.
#1662

@OlaviSau
Copy link
Contributor

OlaviSau commented Jan 3, 2025

@capricorn86 I would love for your feedback on this.

capricorn86 pushed a commit that referenced this issue Jan 7, 2025
* feat: [1502] Allow fetch to be intercepted and modified

* feat: [1502] Add the possibility to intercept sync requests

* fix: [1502] Correct the types for sync response hooks

* feat: [1502] Allow fetch response to be intercepted

* fix: [1502] Move async task manager to be ended after the intercept

* fix: [1502] The interceptor not always being there
@capricorn86
Copy link
Owner

capricorn86 commented Jan 7, 2025

Thanks to @OlaviSau, support for this is now available in the latest release ⭐

You can read more about the release here:
https://github.com/capricorn86/happy-dom/releases/tag/v16.4.0

@capricorn86
Copy link
Owner

So this situation just broke my SSR. I have GTM in code (which, okay is incorrect to have in SSR) and I got error

DOMException: Failed to perform request to "https://www.googletagmanager.com/gtm.js?id=...%3Em_auth=%3Em_preview=%3Em_cookies_win=x". Status 404 Not Found.

And it simply crashed my SSR. So, please, provide more options for handling fetches of external resources.

@mariusrak I'm sorry that you seem to have gotten some critical issues that where blocked by this. It is not easy for me to find the time sometimes to fix all I want to fix in Happy DOM that is needed by the community.

Please take a look at the the latest release and see if it solves your problem. If not, can you open a new ticket detailing a bit what you are missing in a more "advanced" implementation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants