diff --git a/src/server/httpServer.ts b/src/server/httpServer.ts index b89f3f6f..8c845335 100644 --- a/src/server/httpServer.ts +++ b/src/server/httpServer.ts @@ -22,6 +22,7 @@ export class HttpServer extends Disposable { private _server?: http.Server; private _contentLoader: ContentLoader; private _defaultHeaders: any; // headers will be validated when set on the reponse + private _defaultPathExtensions: string[]; private readonly _onNewReqProcessed = this._register( new vscode.EventEmitter() @@ -38,12 +39,16 @@ export class HttpServer extends Disposable { this._contentLoader = this._register( new ContentLoader(_extensionUri, _reporter, _endpointManager, _connection) ); - this._defaultHeaders = SettingUtil.GetConfig().httpHeaders; + const config = SettingUtil.GetConfig(); + this._defaultHeaders = config.httpHeaders; + this._defaultPathExtensions = config.pathExtensions; this._register( vscode.workspace.onDidChangeConfiguration((e) => { if (e.affectsConfiguration(SETTINGS_SECTION_ID)) { - this._defaultHeaders = SettingUtil.GetConfig().httpHeaders; + const config = SettingUtil.GetConfig(); + this._defaultHeaders = config.httpHeaders; + this._defaultPathExtensions = config.pathExtensions; } }) ); @@ -253,7 +258,26 @@ export class HttpServer extends Disposable { } // path should be valid now - const absPathExistsStatInfo = await PathUtil.FileExistsStat(absoluteReadPath); + let absPathExistsStatInfo = await PathUtil.FileExistsStat(absoluteReadPath); + if (!absPathExistsStatInfo.exists) { + // first determine whether this path already includes an extension + const fileName = URLPathName.substring( + URLPathName.lastIndexOf('/') + 1 + ); + // if this path has no extension, try to match paths with whitelisted extensions + if (!fileName.includes('.')) { + for (let i = 0; i < this._defaultPathExtensions.length; i++) { + const modifiedAbsoluteReadPath = absoluteReadPath + this._defaultPathExtensions[i]; + const modifiedAbsPathExistsStatInfo = await PathUtil.FileExistsStat(modifiedAbsoluteReadPath); + if (modifiedAbsPathExistsStatInfo.exists) { + // if a path with added extension exists, use it and stop checking + absoluteReadPath = modifiedAbsoluteReadPath; + absPathExistsStatInfo = modifiedAbsPathExistsStatInfo; + break; + } + } + } + } if (!absPathExistsStatInfo.exists) { writePageNotFound(); return; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 5f05dabf..2d71eb7c 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -37,4 +37,6 @@ export const LIVE_PREVIEW_SERVER_ON = 'LivePreviewServerOn'; export const TASK_TERMINAL_BASE_NAME = vscode.l10n.t('Run Server'); -export const DEFAULT_HTTP_HEADERS = { 'Accept-Ranges': 'bytes' }; \ No newline at end of file +export const DEFAULT_HTTP_HEADERS = { 'Accept-Ranges': 'bytes' }; + +export const DEFAULT_PATH_EXTENSIONS = [ '.html', '.htm' ]; \ No newline at end of file diff --git a/src/utils/settingsUtil.ts b/src/utils/settingsUtil.ts index b6b2a172..0069b158 100644 --- a/src/utils/settingsUtil.ts +++ b/src/utils/settingsUtil.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { DEFAULT_HTTP_HEADERS } from './constants'; +import { DEFAULT_HTTP_HEADERS, DEFAULT_PATH_EXTENSIONS } from './constants'; /** * @description the object representation of the extension settings. @@ -24,6 +24,7 @@ export interface ILivePreviewConfigItem { serverRoot: string; previewDebounceDelay: number; httpHeaders: any; + pathExtensions: string[]; } /** @@ -74,7 +75,8 @@ export const Settings: any = { customExternalBrowser: 'customExternalBrowser', serverRoot: 'serverRoot', previewDebounceDelay: 'previewDebounceDelay', - httpHeaders: 'httpHeaders' + httpHeaders: 'httpHeaders', + pathExtensions: 'pathExtensions' }; /** @@ -132,6 +134,7 @@ export class SettingUtil { customExternalBrowser: config.get(Settings.customExternalBrowser, CustomExternalBrowser.default), serverRoot: config.get(Settings.serverRoot, ''), httpHeaders: config.get(Settings.httpHeaders, DEFAULT_HTTP_HEADERS), + pathExtensions: config.get(Settings.pathExtensions, DEFAULT_PATH_EXTENSIONS), }; }