Skip to content

Commit 2ea238a

Browse files
committed
Add support for wildcard media types
1 parent 6ca978e commit 2ea238a

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

lib/media-types/media-types.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { parse as parseContentType } from "content-type";
2+
import { match as mediaTypeMatch } from "type-is";
23

34

45
const mediaTypePlugins = {};
@@ -22,13 +23,15 @@ export const parseResponse = (response) => {
2223
}
2324

2425
const contentType = parseContentType(contentTypeText);
25-
if (!(contentType.type in mediaTypePlugins)) {
26-
throw new UnsupportedMediaTypeError(contentType.type, `'${contentType.type}' is not supported. Use the 'addMediaTypePlugin' function to add support for this media type.`, {
27-
cause: response
28-
});
26+
for (const pattern in mediaTypePlugins) {
27+
if (mediaTypeMatch(pattern, contentType.type)) {
28+
return mediaTypePlugins[pattern].parse(response);
29+
}
2930
}
3031

31-
return mediaTypePlugins[contentType.type].parse(response);
32+
throw new UnsupportedMediaTypeError(contentType.type, `'${contentType.type}' is not supported. Use the 'addMediaTypePlugin' function to add support for this media type.`, {
33+
cause: response
34+
});
3235
};
3336

3437
export const getFileMediaType = async (path) => {

lib/media-types/media-types.spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, test, beforeEach, afterEach, expect } from "vitest";
2-
import { addMediaTypePlugin, removeMediaTypePlugin, setMediaTypeQuality } from "../index.js";
2+
import { MockAgent, setGlobalDispatcher } from "undici";
3+
import { addMediaTypePlugin, get, removeMediaTypePlugin, setMediaTypeQuality } from "../index.js";
34
import { acceptableMediaTypes } from "./media-types.js";
45

56

@@ -76,5 +77,40 @@ describe("JSON Browser", () => {
7677
expect(accept).to.equal("application/reference+json, application/foo; q=0.9, */*; q=0.001");
7778
});
7879
});
80+
81+
describe("Wildcard media type plugins", () => {
82+
const testDomain = "https://example.com";
83+
let mockAgent: MockAgent;
84+
85+
beforeEach(() => {
86+
addMediaTypePlugin("application/*+foo", {
87+
parse: async () => { // eslint-disable-line @typescript-eslint/require-await
88+
return {
89+
baseUri: "https://exmple.com/foo",
90+
root: null,
91+
anchorLocation: (fragment) => fragment ?? ""
92+
};
93+
},
94+
fileMatcher: async (path) => path.endsWith(".foo") // eslint-disable-line @typescript-eslint/require-await
95+
});
96+
97+
mockAgent = new MockAgent();
98+
mockAgent.disableNetConnect();
99+
setGlobalDispatcher(mockAgent);
100+
mockAgent.get(testDomain)
101+
.intercept({ method: "GET", path: "/foo" })
102+
.reply(200, `{}`, { headers: { "content-type": "application/whatever+foo" } });
103+
});
104+
105+
afterEach(async () => {
106+
removeMediaTypePlugin("application/*+foo");
107+
await mockAgent.close();
108+
});
109+
110+
test("should match wildcard media type", async () => {
111+
// Expect not to throw
112+
await get(`${testDomain}/foo`);
113+
});
114+
});
79115
});
80116
});

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"@hyperjump/json-pointer": "^1.1.0",
5353
"@hyperjump/uri": "^1.2.0",
5454
"content-type": "^1.0.5",
55-
"just-curry-it": "^5.3.0"
55+
"just-curry-it": "^5.3.0",
56+
"type-is": "^1.6.18"
5657
}
5758
}

0 commit comments

Comments
 (0)