-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #47 from internxt/feature/webdav-download
- Loading branch information
Showing
31 changed files
with
750 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Request } from 'express'; | ||
import path from 'path'; | ||
import { WebDavRequestedResource } from '../types/webdav.types'; | ||
export class WebDavUtils { | ||
static getHref(...pathComponents: string[]): string { | ||
return path.posix.join(...pathComponents); | ||
} | ||
static getRequestedResource(req: Request): WebDavRequestedResource { | ||
const decodedUrl = decodeURI(req.url); | ||
const parsedPath = path.parse(decodedUrl); | ||
|
||
if (req.url.endsWith('/')) { | ||
return { | ||
url: decodedUrl, | ||
type: 'folder', | ||
name: parsedPath.name, | ||
path: parsedPath, | ||
}; | ||
} else { | ||
return { | ||
type: 'file', | ||
url: decodedUrl, | ||
name: parsedPath.name, | ||
path: parsedPath, | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { WebDavMethodHandler, WebDavRequestedResource } from '../../types/webdav.types'; | ||
import { Request, Response } from 'express'; | ||
import { WebDavUtils } from '../../utils/webdav.utils'; | ||
import { DriveFileService } from '../../services/drive/drive-file.service'; | ||
import { DriveRealmManager } from '../../services/realms/drive-realm-manager.service'; | ||
import { NetworkFacade } from '../../services/network/network-facade.service'; | ||
import { UploadService } from '../../services/network/upload.service'; | ||
import { DownloadService } from '../../services/network/download.service'; | ||
import { CryptoService } from '../../services/crypto.service'; | ||
import { AuthService } from '../../services/auth.service'; | ||
import { DriveFileRealmSchema } from '../../services/realms/drive-files.realm'; | ||
import { NotFoundError, NotImplementedError } from '../../utils/errors.utils'; | ||
import { webdavLogger } from '../../utils/logger.utils'; | ||
|
||
export class GETRequestHandler implements WebDavMethodHandler { | ||
constructor( | ||
private dependencies: { | ||
driveFileService: DriveFileService; | ||
driveRealmManager: DriveRealmManager; | ||
uploadService: UploadService; | ||
downloadService: DownloadService; | ||
cryptoService: CryptoService; | ||
authService: AuthService; | ||
networkFacade: NetworkFacade; | ||
}, | ||
) {} | ||
handle = async (req: Request, res: Response) => { | ||
const resource = WebDavUtils.getRequestedResource(req); | ||
|
||
if (req.headers['content-range'] || req.headers['range']) | ||
throw new NotImplementedError('Range requests not supported'); | ||
if (resource.name.startsWith('._')) throw new NotFoundError('File not found'); | ||
|
||
webdavLogger.info(`GET request received for file at ${resource.url}`); | ||
const driveFile = await this.getDriveFileRealmObject(resource); | ||
|
||
if (!driveFile) { | ||
throw new NotFoundError('Drive file not found'); | ||
} | ||
|
||
webdavLogger.info(`✅ Found Drive File with uuid ${driveFile.uuid}`); | ||
|
||
res.set('Content-Type', 'application/octet-stream'); | ||
res.set('Content-length', driveFile.size.toString()); | ||
|
||
const { mnemonic } = await this.dependencies.authService.getAuthDetails(); | ||
webdavLogger.info('✅ Network ready for download'); | ||
|
||
const writable = new WritableStream({ | ||
write(chunk) { | ||
res.write(chunk); | ||
}, | ||
close() { | ||
res.end(); | ||
}, | ||
}); | ||
|
||
const [executeDownload] = await this.dependencies.networkFacade.downloadToStream( | ||
driveFile.bucket, | ||
mnemonic, | ||
driveFile.file_id, | ||
writable, | ||
{ | ||
progressCallback: (progress) => { | ||
webdavLogger.info(`Download progress for file ${resource.name}: ${progress}%`); | ||
}, | ||
}, | ||
); | ||
webdavLogger.info('✅ Download prepared, executing...'); | ||
res.status(200); | ||
|
||
await executeDownload; | ||
|
||
webdavLogger.info('✅ Download ready, replying to client'); | ||
}; | ||
|
||
private async getDriveFileRealmObject(resource: WebDavRequestedResource) { | ||
const { driveRealmManager } = this.dependencies; | ||
|
||
const result = await driveRealmManager.findByRelativePath(resource.url); | ||
|
||
return result as DriveFileRealmSchema | null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { WebDavMethodHandler } from '../../types/webdav.types'; | ||
import { Request, Response } from 'express'; | ||
export class HEADRequestHandler implements WebDavMethodHandler { | ||
async handle(req: Request, res: Response) { | ||
// This is a NOOP request handler, clients like CyberDuck uses this. | ||
res.status(405).send(); | ||
} | ||
} |
Oops, something went wrong.