Skip to content

Commit

Permalink
#237 improve binary support
Browse files Browse the repository at this point in the history
  • Loading branch information
Carmine DiMascio committed Feb 22, 2020
1 parent c867a2c commit e6f1926
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 7 deletions.
38 changes: 32 additions & 6 deletions src/middlewares/openapi.multipart.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import { OpenApiContext } from '../framework/openapi.context';
import { createRequestAjv } from '../framework/ajv';
import { validationError } from './util';
import { Request } from 'express';
import {
OpenAPIV3,
OpenApiRequest,
OpenApiRequestHandler,
ValidationError,
} from '../framework/types';
import { MulterError } from 'multer';
import ajv = require('ajv');

const multer = require('multer');

export function multipart(
OpenApiContext: OpenApiContext,
context: OpenApiContext,
multerOpts: {},
): OpenApiRequestHandler {
const mult = multer(multerOpts);
const Ajv = createRequestAjv(context.apiDoc, {});
return (req, res, next) => {
// TODO check that format: binary (for upload) else do not use multer.any()
// use multer.none() if no binary parameters exist
if (isMultipart(req) && isValidContentType(req)) {
if (shouldHandle(Ajv, req)) {
mult.any()(req, res, err => {
if (err) {
next(error(req, err));
Expand Down Expand Up @@ -66,9 +69,32 @@ export function multipart(
};
}

function isValidContentType(req: Request): boolean {
const contentType = req.headers['content-type'];
return !contentType || contentType.includes('multipart/form-data');
function shouldHandle(Ajv, req: OpenApiRequest): boolean {
const reqContentType = req.headers['content-type'];
if (isMultipart(req) && reqContentType?.includes('multipart/form-data')) {
return true;
}

const bodyRef = (<any>req?.openapi)?.schema?.$ref;
const requestBody = bodyRef
? Ajv.getSchema(bodyRef)
: (<any>req?.openapi)?.schema?.requestBody;
const tmp = requestBody?.content;
if (!tmp) return false;

const content = <{ [media: string]: OpenAPIV3.MediaTypeObject }>tmp;
const contentTypes = Object.entries(content);
for (const [contentType, mediaType] of contentTypes) {
if (!contentType.includes(reqContentType)) continue;
const mediaTypeSchema = <any>mediaType?.schema;
const schema = mediaTypeSchema?.$ref
? Ajv.getSchema(mediaTypeSchema.$ref)
: mediaTypeSchema;
const format = schema?.format;
if (format === 'binary') {
return true;
}
}
}

function isMultipart(req: OpenApiRequest): boolean {
Expand Down
Binary file added test/assets/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 14 additions & 1 deletion test/multipart.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as express from 'express';
import * as path from 'path';
import * as fs from 'fs';
import { expect } from 'chai';
import * as request from 'supertest';
import { createApp } from './common/app';
Expand Down Expand Up @@ -33,7 +34,8 @@ describe(packageJson.name, () => {
metadata: req.body.metadata,
});
})
.post(`/sample_1`, (req, res) => res.json(req.body)),
.post(`/sample_1`, (req, res) => res.json(req.body))
.post(`/sample_3`, (req, res) => res.json(req.body)),
),
);
});
Expand Down Expand Up @@ -67,6 +69,17 @@ describe(packageJson.name, () => {
.attach('file', 'package.json')
.expect(400));

it('should validate application/octet-stream file and metadata', done => {
const testImage = `${__dirname}/assets/image.png`;
const req = request(app)
.post(`${app.basePath}/sample_3`)
.set('content-type', 'application/octet-stream');

const imgStream = fs.createReadStream(testImage);
imgStream.on('end', () => req.end(done));
imgStream.pipe(<any>req, { end: false });
});

it('should validate multipart file and metadata', async () => {
await request(app)
.post(`${app.basePath}/sample_2`)
Expand Down
13 changes: 13 additions & 0 deletions test/resources/multipart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,19 @@ paths:
responses:
"200":
description: form data
/sample_3:
post:
description: upload a photo of the pet
operationId: octetStream
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
"200":
description: binary
/range:
get:
parameters:
Expand Down

0 comments on commit e6f1926

Please sign in to comment.