Skip to content

Commit 7c1be3b

Browse files
committed
TW-1733 Fix DELETE methods and handling methods with non-JSON data
1 parent 137db1d commit 7c1be3b

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

src/routers/google-drive.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
import axios, { AxiosRequestHeaders, AxiosResponse, AxiosResponseHeaders } from 'axios';
22
import { Router } from 'express';
33
import { IncomingHttpHeaders } from 'http';
4+
import { omit } from 'lodash';
5+
import { object as objectSchema, mixed as mixedSchema, string as stringSchema } from 'yup';
46

57
import { EnvVars } from '../config';
8+
import { isDefined } from '../utils/helpers';
9+
import logger from '../utils/logger';
610

711
export const googleDriveRouter = Router();
812

913
const googleDriveApi = axios.create({
1014
baseURL: 'https://www.googleapis.com'
1115
});
1216

13-
const allowedBodyMethods = ['post', 'patch', 'delete'] as const;
14-
const isAllowedBodyMethod = (method: string): method is (typeof allowedBodyMethods)[number] =>
15-
allowedBodyMethods.includes(method as (typeof allowedBodyMethods)[number]);
17+
type AllowedBodyMethod = 'post' | 'patch';
18+
const allowedBodyMethods = ['post', 'patch'];
19+
const isAllowedBodyMethod = (method: string): method is AllowedBodyMethod => allowedBodyMethods.includes(method);
20+
type AllowedNoBodyMethod = 'get' | 'delete';
21+
const allowedNoBodyMethods = ['get', 'delete'];
22+
const isAllowedNoBodyMethod = (method: string): method is AllowedNoBodyMethod => allowedNoBodyMethods.includes(method);
1623

1724
const toAxiosRequestHeaders = (headers: IncomingHttpHeaders): AxiosRequestHeaders => {
1825
const axiosHeaders: AxiosRequestHeaders = {};
@@ -37,32 +44,43 @@ const fromAxiosResponseHeaders = (headers: AxiosResponseHeaders): Headers => {
3744
return responseHeaders;
3845
};
3946

47+
const wrappedBodySchema = objectSchema({
48+
body: mixedSchema(),
49+
contentType: stringSchema().required()
50+
}).required();
51+
4052
googleDriveRouter.use(async (req, res) => {
4153
const methodName = req.method.toLowerCase();
4254
try {
4355
const commonRequestConfig = {
4456
params: {
4557
...req.query,
46-
key: req.url.startsWith('/oauth2') ? undefined : EnvVars.GOOGLE_DRIVE_API_KEY
58+
key: req.path.startsWith('/oauth2') ? undefined : EnvVars.GOOGLE_DRIVE_API_KEY
4759
},
48-
headers: {
49-
...toAxiosRequestHeaders(req.headers),
50-
'Content-Type': 'application/json'
51-
}
60+
headers: omit(toAxiosRequestHeaders(req.headers), 'connection', 'Connection', 'content-length', 'Content-Length')
5261
};
5362

5463
let response: AxiosResponse;
55-
if (methodName === 'get') {
56-
response = await googleDriveApi.get(req.url, commonRequestConfig);
64+
if (isAllowedNoBodyMethod(methodName)) {
65+
response = await googleDriveApi[methodName](req.path, commonRequestConfig);
5766
} else if (isAllowedBodyMethod(methodName)) {
58-
response = await googleDriveApi[methodName](req.url, req.body, commonRequestConfig);
67+
const requestConfig = { ...commonRequestConfig };
68+
let body = req.body;
69+
try {
70+
const { body: newBody, contentType } = await wrappedBodySchema.validate(req.body);
71+
body = newBody;
72+
const headersContentTypeKey = isDefined(req.headers['content-type']) ? 'content-type' : 'Content-Type';
73+
requestConfig.headers[headersContentTypeKey] = contentType;
74+
} catch {}
75+
response = await googleDriveApi[methodName](req.path, body, requestConfig);
5976
} else {
6077
throw new Error('Method Not Allowed');
6178
}
6279

6380
res.status(response.status).setHeaders(fromAxiosResponseHeaders(response.headers)).send(response.data);
6481
} catch (error) {
65-
if (methodName !== 'get' && !isAllowedBodyMethod(methodName)) {
82+
logger.error('Google Drive API error', error);
83+
if (!isAllowedNoBodyMethod(methodName) && !isAllowedBodyMethod(methodName)) {
6684
return res.status(405).json({ error: 'Method Not Allowed' });
6785
}
6886

0 commit comments

Comments
 (0)