ProjectEvergreen / greenwood

Greenwood is your full-stack workbench for the web, focused on supporting modern web standards and development to help you create your next project.
https://www.greenwoodjs.io
MIT License
94 stars 9 forks source link

leverage `Sec-Fetch-Dest` header for better filtering within Greenwood resource plugins #1222

Open thescientist13 opened 2 months ago

thescientist13 commented 2 months ago

Summary

One caution with Greenwood resource plugins is making sure not to "overlay" match and / or interfere with userland plugins in unexpected ways, partially due to having to rely (only) on extensions for knowing what kind of file a request / resource is. For example, there is a case where two files could have the same extension, like our TypeScript plugin and say if a user had a plugin to support MPEG streams, which could both use .ts extension.

One way Web APIs can help us with that now by sending a header with information about the resource, like if it is a video file, and that is the Sec-Fetch-Dest header.

Here could be an example for our audio resource plugin

class StandardAudioResource extends ResourceInterface {
  constructor(compilation, options) {
    super(compilation, options);

    // https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Audio_codecs
    // https://www.thoughtco.com/audio-file-mime-types-3469485
    this.extensions = ['mid', 'mp3', 'm3u', 'oga', 'ra', 'wav'];
    this.dest = 'audio';
  }

  async shouldServe(url, request) {
    const extension = url.pathname.split('.').pop();

    return url.protocol === 'file:' && this.extensions.includes(extension) && request.headers.get('Sec-Fetch-Dest') === this.dest;
  }

  async serve(url) {
    // ....
  }
}

Details

I think we should apply this to all plugins for consistency, which also means we should be able to remove this break statement we put into the dev server to avoid multiple plugins trying to incompatibly handle the same resource.

We will also need to update some test cases I imagine to send this header explicitly.