hyperjump-io / json-schema

JSON Schema Validation, Annotation, and Bundling. Supports Draft 04, 06, 07, 2019-09, 2020-12, OpenAPI 3.0, and OpenAPI 3.1
https://json-schema.hyperjump.io/
MIT License
216 stars 22 forks source link

Enable fetch options to be customised. #44

Closed dan-j closed 7 months ago

dan-j commented 8 months ago

We're loading schemas over the network which are protected by authentication and we need the ability to customise the request that's made.

I propose a solution where users can implement a callback, say:

type FetchInitOverrider = (init: RequestInit) => RequestInit

And a function to configure it:

let fetchInitOverrider: FetchInitOverrider | undefined = undefined;

export const setFetchInitOverrider => (fn: FetchInitOverrider): void => {
  fetchInitOverrider = fn
}

Then when a URI is fetched, we check for the overrider and call it if present.

Thoughts?

jdesrosiers commented 8 months ago

I've actually been working on a massive update to the internal workings of this library. When done, you'll have the ability to define how schemas are resolved for each URI scheme. You'll be able to use that mechanism to fetch schemas how ever you need. It would look something like this,

addUriSchemePlugin("https", {
  retrieve: (uri) => fetch(uri, { headers: { authentication: getAuthToken() } });
};

It's not a perfect solution, but it's a solution that should be available to you relatively soon. At some point, I want to find a way to support the authentication case without the need for this kind of low level customization. It's good to know people are interested in that functionality.

hellosmithy commented 8 months ago

➕ This would be very useful

jdesrosiers commented 8 months ago

I've released the changes I mentioned in my previous comment. The library now uses @hyperjump/browser to retrieve schemas. You'll use the functions available from that package to customize your HTTP requests.

import { addUriSchemePlugin, acceptableMediaTypes } from "@hyperjump/browser";

const httpSchemePlugin = {
  retrieve: async (uri) => {
    const response = await fetch(uri, { headers: { Accept: acceptableMediaTypes() } });

    if (!response.ok) {
      throw Error(`Failed to retrieve '${uri}'`);
    }

    return response;
  }
};

addUriSchemePlugin("https", httpSchemePlugin);
addUriSchemePlugin("http", httpSchemePlugin);

You'll notice that http: and https: are handled separately. If you require using https:, it's possible to disable handling http: entirely instead of adding the plugin for both schemes.

import { removeUriSchemePlugin } from "@hyperjump/browser";

removeUriSchemePlugin("http");