diff --git a/src/main/server/webServer/index.ts b/src/main/server/webServer/index.ts index 19bd790..7a6003d 100644 --- a/src/main/server/webServer/index.ts +++ b/src/main/server/webServer/index.ts @@ -3,92 +3,104 @@ import fs from 'fs-extra' import path from 'path' import picgo from '@core/picgo' import logger from '../../apis/core/picgo/logger' +import { encodeFilePath } from '~/universal/utils/common' -const defaultPath = process.platform === 'win32' ? 'C:/Users/' : '/' +const defaultPath = process.platform === 'win32' ? 'C:\\Users' : '/' function generateDirectoryListingHtml (files: any[], requestPath: any) { let html = '

Directory Listing

' return html } +function serveDirectory (res: http.ServerResponse, filePath: fs.PathLike, requestPath: any) { + fs.readdir(filePath, (err, files) => { + if (err) { + res.writeHead(500) + res.end('Error listing directory contents') + } else { + res.writeHead(200, { 'Content-Type': 'text/html' }) + res.end(generateDirectoryListingHtml(files, requestPath)) + } + }) +} + +function serveFile (res:http.ServerResponse, filePath: fs.PathLike) { + const readStream = fs.createReadStream(filePath) + readStream.pipe(res) + readStream.on('error', () => { + res.writeHead(500) + res.end('Error reading file') + }) +} + class WebServer { - private server: http.Server - private config: IStringKeyMap + private server!: http.Server + private config!: IStringKeyMap constructor () { - this.config = this.getConfigWithDefaults() - this.server = this.getServer() + this.loadConfig() + this.initServer() } - getConfigWithDefaults (): IStringKeyMap { - const enableWebServer = picgo.getConfig('settings.enableWebServer') || false - const webServerHost = picgo.getConfig('settings.webServerHost') || '0.0.0.0' - const webServerPort = picgo.getConfig('settings.webServerPort') || 37777 - const webServerPath = picgo.getConfig('settings.webServerPath') || defaultPath - return { enableWebServer, webServerHost, webServerPort, webServerPath } + loadConfig (): void { + this.config = { + enableWebServer: picgo.getConfig('settings.enableWebServer') || false, + webServerHost: picgo.getConfig('settings.webServerHost') || '0.0.0.0', + webServerPort: picgo.getConfig('settings.webServerPort') || 37777, + webServerPath: picgo.getConfig('settings.webServerPath') || defaultPath + } } - getServer (): http.Server { - return http.createServer((req, res) => { + initServer (): void { + this.server = http.createServer((req, res) => { const requestPath = req.url?.split('?')[0] - const filePath = path.join(this.config.webServerPath, decodeURIComponent(requestPath as string)) - - fs.stat(filePath, (err, stats) => { - if (err) { - res.writeHead(404) - res.end('404 Not Found') - return - } + const filePath = path.join(this.config.webServerPath, decodeURIComponent(requestPath || '')) + try { + const stats = fs.statSync(filePath) if (stats.isDirectory()) { - fs.readdir(filePath, (err, files) => { - if (err) { - res.writeHead(500) - res.end('Error listing directory contents') - } else { - res.writeHead(200, { 'Content-Type': 'text/html' }) - res.end(generateDirectoryListingHtml(files, requestPath)) - } - }) + serveDirectory(res, filePath, requestPath) } else { - fs.readFile(filePath, (err, data) => { - if (err) { - res.writeHead(404) - res.end('404 Not Found') - } else { - res.end(data) - } - }) + serveFile(res, filePath) } - }) + } catch (err) { + res.writeHead(404) + res.end('404 Not Found') + } }) } start () { if (this.config.enableWebServer) { - this.server.listen(this.config.webServerPort, this.config.webServerHost, () => { - logger.info(`Web server is running, http://${this.config.webServerHost}:${this.config.webServerPort}, root path is ${this.config.webServerPath}`) - }).on('error', (err) => { - logger.error(err) - }) + this.server + .listen( + this.config.webServerPort === 36699 ? 37777 : this.config.webServerPort, + this.config.webServerHost, () => { + logger.info(`Web server is running at http://${this.config.webServerHost}:${this.config.webServerPort}, root path is ${this.config.webServerPath}`) + }) + .on('error', (err) => { + logger.error(err) + }) } else { logger.info('Web server is not enabled') } } stop () { - this.server.close() - logger.info('Web server is stopped') + this.server.close(() => { + logger.info('Web server is stopped') + }) } restart () { this.stop() - this.config = this.getConfigWithDefaults() - this.server = this.getServer() + this.loadConfig() + this.initServer() this.start() } } diff --git a/src/universal/utils/common.ts b/src/universal/utils/common.ts index 40f381d..94f516b 100644 --- a/src/universal/utils/common.ts +++ b/src/universal/utils/common.ts @@ -52,3 +52,9 @@ export function safeSliceF (str:string, total: number) { } return result } + +export function encodeFilePath (filePath: string) { + filePath = filePath.replace(/\\/g, '/') + const parts = filePath.split('/') + return parts.map(encodeURIComponent).join('/') +}