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

Allow JSDOMRunner to load external resources from specified URLs #172

Merged
merged 1 commit into from
May 23, 2024

Conversation

deej-io
Copy link
Contributor

@deej-io deej-io commented May 21, 2024

For a bit of fun, I'm doing some experimentation with Server-Side rendering technologies to serve and update MML documents - specifically using Go and HTMX . I have a repo with a scrappy, WIP demo here: https://github.com/deej-io/mml-htmx-demo.

The first thing I had to do was update the JSDOMRunner code to allow it to load external resources. Of course this should be disabled by default, as we can't allow people to run arbitrary JavaScript on the MML server, but I thought it might good to have a way of specify allowed resource URLs that can be fetched the runner (in the above demo's case the HTMX library from unpkg).

This is just a WIP to get the discussion going as I'm not happy with the API as it currently stands as we have to thread the URLs through a number of constructors. I am perhaps wondering if a RunnerFactoryFactory approach would be a bit nicer.

Regardless, I wanted to raise this to get your thoughts and make sure there is appetite for this change before I put any more effort into it.


What kind of changes does your PR introduce? (check at least one)

  • Bugfix
  • Feature
  • Refactor
  • Tests
  • Other, please describe:

Does your PR introduce a breaking change? (check one)

  • Yes
  • No

If yes, please describe its impact and migration path for existing applications:

Does your PR fulfill the following requirements?

  • All tests are passing

@deej-io deej-io marked this pull request as draft May 21, 2024 15:21
@MarcusLongmuir
Copy link
Collaborator

Hey. HTMX + MML is a cool idea, and making this configurable makes sense anyway.

The resource loading is disabled because when we were doing initial explorations of doing live editing and the JSDOM instance was being reloaded rapidly it would cause the referenced <scripts> to be repeated retrieved without caching which could be substantial.

The ability to run a remote <script src="https://..."> vs include the same JavaScript directly isn't really a security concern as you could always just fetch the script contents and eval it anyway.

As a result I think making it configurable is a good idea. It can only really apply to the JSDOMRunner class though so I'd propose that rather than drilling the options all the way through the EditableNetworkedDOM instead if non-default configuration of the JSDOMRunner is required (to pass this config to allow resources) then the factory functions to use for ObservableDOM and DOMRunnerFactory are inlined e.g.:

const document = new EditableNetworkedDOM(
  `<script src="http://example.com/script.js"/>`,
  (
    observableDOMParameters: ObservableDOMParameters,
    callback: (message: ObservableDOMMessage, observableDOM: ObservableDOMInterface) => void,
  ): ObservableDOMInterface => {
    return new ObservableDOM(
      observableDOMParameters,
      callback,
      (
        htmlPath: string,
        htmlContents: string,
        params: object,
        callback: (mutationList: DOMRunnerMessage) => void,
      ): DOMRunnerInterface => {
        return new JSDOMRunner(htmlPath, htmlContents, params, callback, {
          // Configure the JSDOMRunner using this optional config
          allowResourceLoading: true, // Or a an array of allowed URLs
        });
      },
    );
  },
);

I appreciate that this is relatively verbose, but it's keeping the configuration true as this is a config for only one of the potential runners.

@deej-io deej-io force-pushed the main branch 3 times, most recently from a5abd06 to 204795d Compare May 22, 2024 09:28
@deej-io deej-io marked this pull request as ready for review May 22, 2024 09:31
@deej-io
Copy link
Contributor Author

deej-io commented May 22, 2024

Thank you for the feedback @MarcusLongmuir - that all makes complete sense.

I've push those changes and checked it is all still working in my demo app 👍 .

I'm loving HTMX right now and it seems to work quite well with MML, but unfortunately it requires a fix to JSDOM, which may not be merged for a while: jsdom/jsdom#3719.

However, it should be as simple as overriding the dependency in package.json of the consuming project, if you did want to use it:

{
  "dependencies": {
    "@mml-io/observable-dom": "*",
  },
  "overrides": {
    "@mml-io/observable-dom": {
      "jsdom": "deej-io/jsdom",
    }
  }
}

@deej-io deej-io changed the title allow networked DOM servers to load external resources from specified URLs Allow JSDOMRunner to load external resources from specified URLs May 22, 2024
this.urls = urls
}
public fetch(url: string, opts?: FetchOptions): AbortablePromise<Buffer> | null {
const allow = this.urls.every(allowedURL => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const allow = this.urls.every(allowedURL => {
const allow = this.urls.some(allowedURL => {

I think this is meant to be "if any of the rules / addresses allow this resource", right?

Copy link
Contributor Author

@deej-io deej-io May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, thanks.

That's on me only testing with one resource URL 🤦‍♂️.

I'll add some unit tests for it.

Copy link
Collaborator

@MarcusLongmuir MarcusLongmuir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, @deej-io 👍

@MarcusLongmuir MarcusLongmuir merged commit e949a19 into mml-io:main May 23, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants