Skip to content

Commit b4825f4

Browse files
committed
improved webdav logging
1 parent f8dd1d5 commit b4825f4

10 files changed

Lines changed: 54 additions & 42 deletions

File tree

src/utils/errors.utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ export class UnsupportedMediaTypeError extends Error {
5050
}
5151
}
5252

53+
export class MethodNotAllowed extends Error {
54+
public statusCode = 405;
55+
56+
constructor(message: string) {
57+
super(message);
58+
this.name = 'MethodNotAllowed';
59+
Object.setPrototypeOf(this, MethodNotAllowed.prototype);
60+
}
61+
}
62+
5363
export class NotImplementedError extends Error {
5464
public statusCode = 501;
5565

src/utils/logger.utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const maxLogsFiles = 5;
66

77
export const logger = winston.createLogger({
88
level: 'info',
9-
format: winston.format.json(),
9+
format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
1010
defaultMeta: { service: 'internxt-cli' },
1111
transports: [
1212
new winston.transports.File({
@@ -29,7 +29,7 @@ export const logger = winston.createLogger({
2929

3030
export const webdavLogger = winston.createLogger({
3131
level: 'info',
32-
format: winston.format.json(),
32+
format: winston.format.combine(winston.format.timestamp(), winston.format.json()),
3333
defaultMeta: { service: 'internxt-webdav' },
3434
transports: [
3535
new winston.transports.File({

src/webdav/handlers/DELETE.handler.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ export class DELETERequestHandler implements WebDavMethodHandler {
1919

2020
handle = async (req: Request, res: Response) => {
2121
const { driveDatabaseManager, driveFileService, driveFolderService, trashService } = this.dependencies;
22-
webdavLogger.info('DELETE request received');
2322
const resource = await WebDavUtils.getRequestedResource(req);
24-
webdavLogger.info('Resource received for DELETE request', { resource });
23+
webdavLogger.info(`[DELETE] Request received for ${resource.type} at ${resource.url}`);
2524

2625
const driveItem = await WebDavUtils.getAndSearchItemFromResource({
2726
resource,
@@ -30,7 +29,7 @@ export class DELETERequestHandler implements WebDavMethodHandler {
3029
driveFileService: driveFileService,
3130
});
3231

33-
webdavLogger.info(`Trashing ${resource.type} with UUID ${driveItem.uuid}...`);
32+
webdavLogger.info(`[DELETE] [${driveItem.uuid}] Trashing ${resource.type}`);
3433
await trashService.trashItems({
3534
items: [{ type: resource.type, uuid: driveItem.uuid }],
3635
});
@@ -42,5 +41,7 @@ export class DELETERequestHandler implements WebDavMethodHandler {
4241
}
4342

4443
res.status(204).send();
44+
const type = resource.type.charAt(0).toUpperCase() + resource.type.substring(1);
45+
webdavLogger.info(`[DELETE] [${driveItem.uuid}] ${type} trashed successfully`);
4546
};
4647
}

src/webdav/handlers/GET.handler.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { WebDavUtils } from '../../utils/webdav.utils';
44
import { DriveFileService } from '../../services/drive/drive-file.service';
55
import { DriveDatabaseManager } from '../../services/database/drive-database-manager.service';
66
import { NetworkFacade } from '../../services/network/network-facade.service';
7-
import { UploadService } from '../../services/network/upload.service';
87
import { DownloadService } from '../../services/network/download.service';
98
import { CryptoService } from '../../services/crypto.service';
109
import { AuthService } from '../../services/auth.service';
@@ -18,7 +17,6 @@ export class GETRequestHandler implements WebDavMethodHandler {
1817
private readonly dependencies: {
1918
driveFileService: DriveFileService;
2019
driveDatabaseManager: DriveDatabaseManager;
21-
uploadService: UploadService;
2220
downloadService: DownloadService;
2321
cryptoService: CryptoService;
2422
authService: AuthService;
@@ -31,18 +29,19 @@ export class GETRequestHandler implements WebDavMethodHandler {
3129
const resource = await WebDavUtils.getRequestedResource(req);
3230

3331
if (resource.name.startsWith('._')) throw new NotFoundError('File not found');
32+
if (resource.type === 'folder') throw new NotFoundError('Folders cannot be listed with GET. Use PROPFIND instead.');
3433

35-
webdavLogger.info(`GET request received for file at ${resource.url}`);
34+
webdavLogger.info(`[GET] Request received for ${resource.type} at ${resource.url}`);
3635
const driveFile = (await WebDavUtils.getAndSearchItemFromResource({
3736
resource,
3837
driveDatabaseManager,
3938
driveFileService,
4039
})) as DriveFileItem;
4140

42-
webdavLogger.info(`✅ Found Drive File with uuid ${driveFile.uuid}`);
41+
webdavLogger.info(`[GET] [${driveFile.uuid}] Found Drive File`);
4342

4443
const { user } = await authService.getAuthDetails();
45-
webdavLogger.info('✅ Network ready for download');
44+
webdavLogger.info(`[GET] [${driveFile.uuid}] Network ready for download`);
4645

4746
const writable = new WritableStream({
4847
write(chunk) {
@@ -60,36 +59,25 @@ export class GETRequestHandler implements WebDavMethodHandler {
6059
});
6160
let contentLength = driveFile.size;
6261
if (rangeOptions) {
63-
webdavLogger.info('✅ Range request received:', { rangeOptions });
62+
webdavLogger.info(`[GET] [${driveFile.uuid}] Range request received:`, { rangeOptions });
6463
contentLength = rangeOptions.rangeSize;
6564
}
6665

67-
res.set('Content-Type', 'application/octet-stream');
68-
res.set('Content-length', contentLength.toString());
66+
res.header('Content-Type', 'application/octet-stream');
67+
res.header('Content-length', contentLength.toString());
6968

70-
let lastLoggedProgress = 0;
7169
const [executeDownload] = await networkFacade.downloadToStream(
7270
driveFile.bucket,
7371
user.mnemonic,
7472
driveFile.fileId,
7573
writable,
7674
rangeOptions,
77-
{
78-
progressCallback: (progress) => {
79-
const percentage = Math.floor(100 * progress);
80-
81-
if (percentage >= lastLoggedProgress + 1) {
82-
lastLoggedProgress = percentage;
83-
webdavLogger.info(`Download progress for file ${resource.name}: ${percentage}%`);
84-
}
85-
},
86-
},
8775
);
88-
webdavLogger.info('✅ Download prepared, executing...');
76+
webdavLogger.info(`[GET] [${driveFile.uuid}] Download prepared, executing...`);
8977
res.status(200);
9078

9179
await executeDownload;
9280

93-
webdavLogger.info('✅ Download ready, replying to client');
81+
webdavLogger.info(`[GET] [${driveFile.uuid}] ✅ Download ready, replying to client`);
9482
};
9583
}

src/webdav/handlers/MKCOL.handler.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { webdavLogger } from '../../utils/logger.utils';
77
import { XMLUtils } from '../../utils/xml.utils';
88
import { AsyncUtils } from '../../utils/async.utils';
99
import { DriveFolderItem } from '../../types/drive.types';
10+
import { MethodNotAllowed } from '../../utils/errors.utils';
1011

1112
export class MKCOLRequestHandler implements WebDavMethodHandler {
1213
constructor(
@@ -19,7 +20,10 @@ export class MKCOLRequestHandler implements WebDavMethodHandler {
1920
handle = async (req: Request, res: Response) => {
2021
const { driveDatabaseManager, driveFolderService } = this.dependencies;
2122
const resource = await WebDavUtils.getRequestedResource(req);
22-
webdavLogger.info('Resource received for MKCOL request', { resource });
23+
24+
if (resource.type === 'file') throw new MethodNotAllowed('Files cannot be created with MKCOL. Use PUT instead.');
25+
26+
webdavLogger.info(`[MKCOL] Request received for ${resource.type} at ${resource.url}`);
2327

2428
const parentResource = await WebDavUtils.getRequestedResource(resource.parentPath);
2529

@@ -36,7 +40,7 @@ export class MKCOLRequestHandler implements WebDavMethodHandler {
3640

3741
const newFolder = await createFolder;
3842

39-
webdavLogger.info(`✅ Folder created with UUID ${newFolder.uuid}`);
43+
webdavLogger.info(`[MKCOL] ✅ Folder created with UUID ${newFolder.uuid}`);
4044

4145
await driveDatabaseManager.createFolder(
4246
{

src/webdav/handlers/MOVE.handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ export class MOVERequestHandler implements WebDavMethodHandler {
2121
const { driveDatabaseManager, driveFolderService, driveFileService } = this.dependencies;
2222
const resource = await WebDavUtils.getRequestedResource(req);
2323

24-
webdavLogger.info('[MOVE] Resource found', { resource });
24+
webdavLogger.info(`[MOVE] Request received for ${resource.type} at ${resource.url}`);
2525

2626
const destinationUrl = req.header('destination');
2727
if (!destinationUrl) {
28-
throw new NotFoundError('Destination folder not received');
28+
throw new NotFoundError('[MOVE] Destination folder not received');
2929
}
3030
const destinationPath = WebDavUtils.removeHostFromURL(destinationUrl);
3131
const destinationResource = await WebDavUtils.getRequestedResource(destinationPath);

src/webdav/handlers/PROPFIND.handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class PROPFINDRequestHandler implements WebDavMethodHandler {
2525
const { driveDatabaseManager, driveFolderService, driveFileService } = this.dependencies;
2626

2727
const resource = await WebDavUtils.getRequestedResource(req);
28-
webdavLogger.info('[PROPFIND] Request received', { resource });
28+
webdavLogger.info(`[PROPFIND] Request received for ${resource.type} at ${resource.url}`);
2929

3030
const driveItem = await WebDavUtils.getAndSearchItemFromResource({
3131
resource,

src/webdav/handlers/PUT.handler.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DriveFileService } from '../../services/drive/drive-file.service';
33
import { NetworkFacade } from '../../services/network/network-facade.service';
44
import { AuthService } from '../../services/auth.service';
55
import { WebDavMethodHandler } from '../../types/webdav.types';
6-
import { UnsupportedMediaTypeError } from '../../utils/errors.utils';
6+
import { NotFoundError, UnsupportedMediaTypeError } from '../../utils/errors.utils';
77
import { WebDavUtils } from '../../utils/webdav.utils';
88
import { webdavLogger } from '../../utils/logger.utils';
99
import { DriveDatabaseManager } from '../../services/database/drive-database-manager.service';
@@ -33,7 +33,12 @@ export class PUTRequestHandler implements WebDavMethodHandler {
3333
}
3434

3535
const resource = await WebDavUtils.getRequestedResource(req);
36-
webdavLogger.info(`PUT request received for uploading file '${resource.name}' to '${resource.parentPath}'`);
36+
37+
if (resource.type === 'folder') throw new NotFoundError('Folders cannot be created with PUT. Use MKCOL instead.');
38+
39+
webdavLogger.info(`[PUT] Request received for ${resource.type} at ${resource.url}`);
40+
webdavLogger.info(`[PUT] Uploading '${resource.name}' to '${resource.parentPath}'`);
41+
3742
const parentResource = await WebDavUtils.getRequestedResource(resource.parentPath);
3843

3944
const parentFolderItem = (await WebDavUtils.getAndSearchItemFromResource({
@@ -51,7 +56,7 @@ export class PUTRequestHandler implements WebDavMethodHandler {
5156
driveFileService,
5257
})) as DriveFileItem;
5358
if (driveFileItem && driveFileItem.status === 'EXISTS') {
54-
webdavLogger.info(`File '${resource.name}' already exists in '${resource.path.dir}', trashing it before PUT`);
59+
webdavLogger.info(`[PUT] File '${resource.name}' already exists in '${resource.path.dir}', trashing it...`);
5560
await driveDatabaseManager.deleteFileById(driveFileItem.id);
5661
await trashService.trashItems({
5762
items: [{ type: resource.type, uuid: driveFileItem.uuid }],
@@ -70,14 +75,14 @@ export class PUTRequestHandler implements WebDavMethodHandler {
7075

7176
if (percentage >= lastLoggedProgress + 1) {
7277
lastLoggedProgress = percentage;
73-
webdavLogger.info(`Upload progress for file ${resource.name}: ${percentage}%`);
78+
webdavLogger.info(`[PUT] Upload progress for file ${resource.name}: ${percentage}%`);
7479
}
7580
},
7681
});
7782

7883
const uploadResult = await uploadPromise;
7984

80-
webdavLogger.info('✅ File uploaded to network');
85+
webdavLogger.info('[PUT] ✅ File uploaded to network');
8186

8287
const file = await DriveFileService.instance.createFile({
8388
plain_name: resource.path.name,
@@ -90,7 +95,7 @@ export class PUTRequestHandler implements WebDavMethodHandler {
9095
name: '',
9196
});
9297

93-
webdavLogger.info('✅ File uploaded to internxt drive');
98+
webdavLogger.info('[PUT] ✅ File uploaded to internxt drive');
9499

95100
await driveDatabaseManager.createFile(file, resource.path.dir + '/');
96101

src/webdav/webdav-server.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,21 @@ export class WebDavServer {
6969

7070
private readonly registerHandlers = async () => {
7171
const networkFacade = await this.getNetworkFacade();
72-
this.app.head('*', asyncHandler(new HEADRequestHandler().handle));
72+
this.app.head(
73+
'*',
74+
asyncHandler(
75+
new HEADRequestHandler({
76+
driveFileService: this.driveFileService,
77+
driveDatabaseManager: this.driveDatabaseManager,
78+
}).handle,
79+
),
80+
);
7381
this.app.get(
7482
'*',
7583
asyncHandler(
7684
new GETRequestHandler({
7785
driveFileService: this.driveFileService,
7886
driveDatabaseManager: this.driveDatabaseManager,
79-
uploadService: this.uploadService,
8087
downloadService: this.downloadService,
8188
cryptoService: this.cryptoService,
8289
authService: this.authService,

test/webdav/handlers/GET.handler.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ describe.skip('GET request handler', () => {
4242
);
4343
const sut = new GETRequestHandler({
4444
driveFileService: DriveFileService.instance,
45-
uploadService: UploadService.instance,
4645
downloadService: DownloadService.instance,
4746
driveDatabaseManager: getDriveDatabaseManager(),
4847
authService: AuthService.instance,
@@ -77,7 +76,6 @@ describe.skip('GET request handler', () => {
7776
const networkFacade = new NetworkFacade(getNetworkMock(), uploadService, downloadService, cryptoService);
7877
const requestHandler = new GETRequestHandler({
7978
driveFileService: DriveFileService.instance,
80-
uploadService,
8179
downloadService,
8280
driveDatabaseManager,
8381
authService: AuthService.instance,
@@ -124,7 +122,6 @@ describe.skip('GET request handler', () => {
124122
const networkFacade = new NetworkFacade(getNetworkMock(), uploadService, downloadService, cryptoService);
125123
const requestHandler = new GETRequestHandler({
126124
driveFileService: DriveFileService.instance,
127-
uploadService,
128125
downloadService,
129126
driveDatabaseManager,
130127
authService,

0 commit comments

Comments
 (0)