import * as path from 'path' ; import * as fs from 'fs-extra' ; import { DiskReaderConfig } from './config' ; const METADATA_DIRNAME = '.gaia-metadata' ; export type GetFileInfo = { exists : boolean ; contentType ? : string ; contentLength ? : number ; etag ? : string ; lastModified ? : Date ; fileReadStream ? : fs . ReadStream ; } ; export class GaiaDiskReader { config : DiskReaderConfig ; constructor ( config ) { this . config = config ; fs . ensureDirSync ( config . diskSettings . storageRootDirectory ) ; } isPathValid ( path ) { return ! path . includes ( '..' ) ; } async handleGet ( topLevelDir , filename , openFileStream ) { const storageRoot = this . config . diskSettings . storageRootDirectory ; if ( ! storageRoot ) { throw new Error ( 'Misconfiguration: no storage root set' ) ; } if ( ! this . isPathValid ( filename ) ) { throw new Error ( 'Invalid file name' ) ; } const filePath = path . join ( storageRoot , topLevelDir , filename ) ; let stat ; try { stat = await fs . stat ( filePath ) ; } catch ( e ) { return { exists : false } ; } let readStream ; try { const metadataPath = path . join ( storageRoot , METADATA_DIRNAME , topLevelDir , filename ) ; let metadata = { } ; try { metadata = await fs . readJson ( metadataPath ) ; } catch ( error ) { metadata [ 'content-type' ] = 'application/octet-stream' ; } if ( openFileStream ) { readStream = fs . createReadStream ( filePath ) ; } return { exists : true , lastModified : stat . mtime , contentLength : stat . size , contentType : metadata [ 'content-type' ] , etag : metadata [ 'etag' ] , fileReadStream : readStream } ; } catch ( error ) { if ( readStream ) { readStream . close ( ) ; } throw error ; } } }