Skip to content

Commit a298dc6

Browse files
alexbaileyukclaude
andauthored
fix(openapi): convert contentEncoding to format for file uploads (#916)
Closes #800 Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e996abc commit a298dc6

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

lib/spec/openapi/utils.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,16 @@ function convertJsonSchemaToOpenapi3 (opts, jsonSchema) {
549549
continue
550550
}
551551

552+
if (key === 'contentEncoding') {
553+
if (value === 'binary') {
554+
openapiSchema.format = 'binary'
555+
} else if (value === 'base64') {
556+
openapiSchema.format = 'byte'
557+
}
558+
delete openapiSchema.contentEncoding
559+
continue
560+
}
561+
552562
if (key === 'patternProperties') {
553563
// TODO: check if additionalProperties property already exists
554564
// TODO: this breaks references to the additionalProperties properties

test/spec/openapi/schema.test.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,84 @@ const {
1010
schemaAllOf
1111
} = require('../../../examples/options')
1212

13+
test('support file in json schema', async t => {
14+
const opts = {
15+
schema: {
16+
consumes: ['multipart/form-data'],
17+
body: {
18+
type: 'object',
19+
properties: {
20+
file: {
21+
description: 'a file',
22+
type: 'string',
23+
contentEncoding: 'binary'
24+
}
25+
},
26+
required: ['file']
27+
}
28+
}
29+
}
30+
31+
const fastify = Fastify()
32+
await fastify.register(fastifySwagger, openapiOption)
33+
fastify.post('/', opts, () => {})
34+
35+
await fastify.ready()
36+
37+
const openapiObject = fastify.swagger()
38+
const api = await Swagger.validate(openapiObject)
39+
40+
const definedPath = api.paths['/'].post
41+
t.assert.ok(definedPath)
42+
t.assert.deepStrictEqual(
43+
definedPath.requestBody.content['multipart/form-data'].schema.properties.file,
44+
{
45+
description: 'a file',
46+
type: 'string',
47+
format: 'binary'
48+
}
49+
)
50+
})
51+
52+
test('support base64 contentEncoding in json schema', async t => {
53+
const opts = {
54+
schema: {
55+
consumes: ['multipart/form-data'],
56+
body: {
57+
type: 'object',
58+
properties: {
59+
file: {
60+
description: 'a base64 file',
61+
type: 'string',
62+
contentEncoding: 'base64'
63+
}
64+
},
65+
required: ['file']
66+
}
67+
}
68+
}
69+
70+
const fastify = Fastify()
71+
await fastify.register(fastifySwagger, openapiOption)
72+
fastify.post('/', opts, () => {})
73+
74+
await fastify.ready()
75+
76+
const openapiObject = fastify.swagger()
77+
const api = await Swagger.validate(openapiObject)
78+
79+
const definedPath = api.paths['/'].post
80+
t.assert.ok(definedPath)
81+
t.assert.deepStrictEqual(
82+
definedPath.requestBody.content['multipart/form-data'].schema.properties.file,
83+
{
84+
description: 'a base64 file',
85+
type: 'string',
86+
format: 'byte'
87+
}
88+
)
89+
})
90+
1391
test('support - oneOf, anyOf, allOf', async (t) => {
1492
t.plan(2)
1593
const fastify = Fastify()

0 commit comments

Comments
 (0)