11import axios , { AxiosRequestHeaders , AxiosResponse , AxiosResponseHeaders } from 'axios' ;
22import { Router } from 'express' ;
33import { IncomingHttpHeaders } from 'http' ;
4+ import { omit } from 'lodash' ;
5+ import { object as objectSchema , mixed as mixedSchema , string as stringSchema } from 'yup' ;
46
57import { EnvVars } from '../config' ;
8+ import { isDefined } from '../utils/helpers' ;
9+ import logger from '../utils/logger' ;
610
711export const googleDriveRouter = Router ( ) ;
812
913const 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
1724const 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+
4052googleDriveRouter . 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