diff --git a/src/fromOpenApi/fromOpenApi.ts b/src/fromOpenApi/fromOpenApi.ts
index f9ef0bf..10a7e9a 100644
--- a/src/fromOpenApi/fromOpenApi.ts
+++ b/src/fromOpenApi/fromOpenApi.ts
@@ -1,5 +1,6 @@
import { invariant } from 'outvariant'
import { datatype, internet, random } from 'faker'
+import { headersToObject } from 'headers-utils'
import { randexp } from 'randexp'
import {
RestContext,
@@ -147,10 +148,23 @@ function createResponseResolver(
if ('content' in response && response.content != null) {
let body: unknown
- const explicitContentType = req.url.searchParams.get('type')
- const contentType = explicitContentType
- ? explicitContentType
- : Object.keys(response.content)[0]
+ const requestHeaders = headersToObject(req.headers)
+ const acceptedMimeTypes = ([] as string[]).concat(requestHeaders.accept)
+ const explicitContentType = acceptedMimeTypes[0]
+ const explicitContentTypeRegexp = new RegExp(
+ explicitContentType.replace(/\/+/g, '\\/').replace(/\*/g, '.+?'),
+ )
+
+ const allContentTypes = Object.keys(response.content)
+
+ const contentType =
+ allContentTypes.find((contentType) => {
+ // Find the first declared response content type
+ // that matches the "Accept" request header.
+ // Keep in mind that values like "*/*" and "application/*"
+ // are completely valid.
+ return explicitContentTypeRegexp.test(contentType)
+ }) || allContentTypes[0]
transformers.push(ctx.set('Content-Type', contentType))
@@ -167,7 +181,7 @@ function createResponseResolver(
mediaTypeObject.examples,
)[0] as OpenAPIV3.ExampleObject
- // Response body must always be string.
+ // Response body must always be a string.
body = value
}
// JSON Schema is populated with random values.
diff --git a/test/oas/oas-json-schema.test.ts b/test/oas/oas-json-schema.test.ts
index 419dd31..c539fb3 100644
--- a/test/oas/oas-json-schema.test.ts
+++ b/test/oas/oas-json-schema.test.ts
@@ -173,3 +173,53 @@ it('responds with 501 to a request for explicit non-existing response status', a
expect(await res.text()).toEqual('')
})
})
+
+it('respects the "Accept" request header', async () => {
+ const handlers = await fromOpenApi(
+ createOpenApiSpec({
+ paths: {
+ '/user': {
+ get: {
+ responses: {
+ 200: {
+ content: {
+ 'application/json': {
+ example: { id: 'user-1' },
+ },
+ 'application/xml': {
+ example: `xml-1`,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }),
+ )
+
+ // The "Accept" request header with a single value.
+ await withHandlers(handlers, () => {
+ return fetch('http://localhost/user', {
+ headers: {
+ Accept: 'application/xml',
+ },
+ })
+ }).then(async (res) => {
+ expect(res.status).toEqual(200)
+ expect(await res.text()).toEqual(`xml-1`)
+ })
+
+ // The "Accept" request header with multiple values.
+ await withHandlers(handlers, () => {
+ return fetch('http://localhost/user', {
+ headers: {
+ Accept: 'application/json, application/xml',
+ },
+ })
+ }).then(async (res) => {
+ expect(res.status).toEqual(200)
+ // The first MimeType is used for the mocked data.
+ expect(await res.text()).toEqual(`{"id":"user-1"}`)
+ })
+})