Skip to content

Commit

Permalink
refactor file handler
Browse files Browse the repository at this point in the history
  • Loading branch information
ujjwalguptaofficial committed Jan 21, 2025
1 parent 9bb387c commit 50d6a8b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 38 deletions.
73 changes: 46 additions & 27 deletions src/handlers/file_handler.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { HTTP_STATUS_CODE, MIME_TYPE, ETAG_TYPE } from "../enums";
import { HTTP_STATUS_CODE, MIME_TYPE, ETAG_TYPE, HTTP_RESULT_TYPE } from "../enums";
import * as path from "path";
import { CONTENT_TYPE } from "../constants";
import * as Fs from "fs";
import { getMimeTypeFromFileType, promise } from "../helpers";
import { getMimeTypeFromExtension, getMimeTypeFromFileType, promise } from "../helpers";
import * as etag from "etag";
import * as fresh from "fresh";
import { isNullOrEmpty } from "../utils";
import { RequestHandler } from "./request_handler";
import { IFileResultInfo, IHttpResult } from "../interfaces";

interface IFileInfo {
folder: string,
Expand All @@ -19,6 +20,13 @@ export class FileHandler {

}

private returnFileResult_(filePath: string, fileInfo: Fs.Stats) {
return {
filePath: filePath,
fileInfo: fileInfo
} as IFileResultInfo;
};

private getFileInfoFromUrl_(urlPath: string) {
const splittedValue = urlPath.split("/");
const fileInfo = {
Expand Down Expand Up @@ -53,20 +61,19 @@ export class FileHandler {
});
}

handleFileRequestFromAbsolutePath(absolutePath: string, fileType: string) {
return this.getFileStats_(absolutePath).then(fileInfo => {
if (fileInfo != null) {
if (fileInfo.isDirectory() === true) {
return this.handleFileRequestForFolderPath_(absolutePath);
}
else {
return this.sendFile_(absolutePath, fileType, fileInfo);
}
async getFileResultFromAbsolutePath(absolutePath: string) {
const fileInfo = await this.getFileStats_(absolutePath);
if (fileInfo != null) {
if (fileInfo.isDirectory() === true) {
return this.getFileResultForFolderPath_(absolutePath);
}
else {
return this.requestHandler.onNotFound();
return this.getFile_(absolutePath, fileInfo);
}
});
}
// else {
// return this.requestHandler.onNotFound();
// }
}

private checkForFolderAllowAndReturnPath_(urlPath: string) {
Expand All @@ -87,15 +94,21 @@ export class FileHandler {
return absPath;
}

handleFileRequest(urlPath: string) {
const extension = path.parse(urlPath).ext;
async handleFileRequest(urlPath: string) {
const absFilePath = this.checkForFolderAllowAndReturnPath_(urlPath);
if (absFilePath != null) {
return this.handleFileRequestFromAbsolutePath(absFilePath, extension);
}
else {
return this.requestHandler.onNotFound();
const filePathInfo = await this.getFileResultFromAbsolutePath(absFilePath);
if (filePathInfo) {
return {
type: HTTP_RESULT_TYPE.File,
responseData: filePathInfo
} as IHttpResult;
}
}
// else {
// return null;
// // return this.requestHandler.onNotFound();
// }
}

/**
Expand All @@ -108,13 +121,12 @@ export class FileHandler {
* @returns
* @memberof FileHandler
*/
private handleFileRequestForFolderPath_(absolutePath: string) {
private async getFileResultForFolderPath_(absolutePath: string) {
absolutePath = path.join(absolutePath, "index.html");
return this.getFileStats_(absolutePath).then(fileInfo => {
return fileInfo != null ?
this.sendFile_(absolutePath, MIME_TYPE.Html, fileInfo) :
this.requestHandler.onNotFound();
});
const fileInfo = await this.getFileStats_(absolutePath);
return fileInfo != null ?
this.getFile_(absolutePath, fileInfo) :
null;
}

protected isClientHasFreshFile(lastModified: string, etagValue: string) {
Expand All @@ -137,20 +149,27 @@ export class FileHandler {
});
}

sendFile_(filePath: string, fileType: string, fileInfo: Fs.Stats) {
send(filePathInfo: IFileResultInfo) {
const { fileInfo, filePath } = filePathInfo;
const lastModified = fileInfo.mtime.toUTCString();
const eTagValue = etag(fileInfo, {
weak: this.requestHandler.config.eTag.type === ETAG_TYPE.Weak
});
const response = this.requestHandler.response;
response.setHeader('Etag', eTagValue);
const extension = path.parse(filePath).ext;
const mimeType = getMimeTypeFromExtension(extension);
if (this.isClientHasFreshFile(lastModified, eTagValue)) { // client has fresh file
response.statusCode = HTTP_STATUS_CODE.NotModified;
response.end();
}
else {
response.setHeader('Last-Modified', lastModified);
this.sendFileAsResponse(filePath, getMimeTypeFromFileType(fileType));
this.sendFileAsResponse(filePath, mimeType);
}
}

private getFile_(filePath: string, fileInfo: Fs.Stats) {
return this.returnFileResult_(filePath, fileInfo);
}
}
16 changes: 11 additions & 5 deletions src/handlers/request_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,19 @@ export class RequestHandler extends RequestHandlerHelper {
return this.handleFinalResult_();
}
const pathUrl = urlDetail.pathname;

this.routeMatchInfo_ = parseAndMatchRoute(pathUrl, request.method as HTTP_METHOD);
const onNotRouteMatched = async () => {
const fileHandler = new FileHandler(this);
const fileResult = await fileHandler.handleFileRequest(pathUrl);
if (fileResult == null) {
return () => {
return this.onNotFound();
}
}
return this.onResultFromComponent(fileResult);
};
const finalCallback = await (
this.routeMatchInfo_ == null ? () => {
const fileHandler = new FileHandler(this);
return fileHandler.handleFileRequest(pathUrl);
} :
this.routeMatchInfo_ == null ? onNotRouteMatched() :
this.onRouteMatched_()
);
await this.runWallOutgoing_();
Expand Down
10 changes: 7 additions & 3 deletions src/handlers/request_handler_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export class RequestHandlerHelper {
return null;
}

private handleFileResult_() {
private async handleFileResult_() {
const result = this.controllerResult as IHttpResult;
const fileResult = result.responseData as IFileResultInfo;
const parsedPath = parse(fileResult.filePath);
Expand All @@ -193,9 +193,13 @@ export class RequestHandlerHelper {
);
}
const fileHandler = new FileHandler(this as any);
return fileHandler.handleFileRequestFromAbsolutePath(
fileResult.filePath, parsedPath.ext
const fileResultForSendingResponse = fileResult.fileInfo ? fileResult : await fileHandler.getFileResultFromAbsolutePath(
fileResult.filePath
);
if (fileResultForSendingResponse == null) {
return this.onNotFound();
}
return fileHandler.send(fileResultForSendingResponse);
}

protected handleFinalResult_() {
Expand Down
9 changes: 6 additions & 3 deletions src/interfaces/file_result_info.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Stats } from "fs";

export interface IFileResultInfo {
filePath: string;
alias: string;
shouldDownload: boolean;
}
alias?: string;
shouldDownload?: boolean;
fileInfo?: Stats
}

0 comments on commit 50d6a8b

Please sign in to comment.