Feature(custom): optimize webServer

This commit is contained in:
Kuingsmile 2024-04-05 15:18:20 +08:00
parent aa9e535fd1
commit e6e94723d0
2 changed files with 67 additions and 49 deletions

View File

@ -3,92 +3,104 @@ import fs from 'fs-extra'
import path from 'path' import path from 'path'
import picgo from '@core/picgo' import picgo from '@core/picgo'
import logger from '../../apis/core/picgo/logger' 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) { function generateDirectoryListingHtml (files: any[], requestPath: any) {
let html = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body><h1>Directory Listing</h1><ul>' let html = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body><h1>Directory Listing</h1><ul>'
files.forEach((file: string) => { files.forEach((file: string) => {
html += `<li><a href="${path.join(requestPath, file)}">${file}</a></li>` const filePath = path.join(requestPath, file)
html += `<li><a href="${encodeFilePath(filePath)}">${file}</a></li>`
}) })
html += '</ul></body></html>' html += '</ul></body></html>'
return html 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 { class WebServer {
private server: http.Server private server!: http.Server
private config: IStringKeyMap private config!: IStringKeyMap
constructor () { constructor () {
this.config = this.getConfigWithDefaults() this.loadConfig()
this.server = this.getServer() this.initServer()
} }
getConfigWithDefaults (): IStringKeyMap { loadConfig (): void {
const enableWebServer = picgo.getConfig<boolean>('settings.enableWebServer') || false this.config = {
const webServerHost = picgo.getConfig<string>('settings.webServerHost') || '0.0.0.0' enableWebServer: picgo.getConfig<boolean>('settings.enableWebServer') || false,
const webServerPort = picgo.getConfig<number>('settings.webServerPort') || 37777 webServerHost: picgo.getConfig<string>('settings.webServerHost') || '0.0.0.0',
const webServerPath = picgo.getConfig<string>('settings.webServerPath') || defaultPath webServerPort: picgo.getConfig<number>('settings.webServerPort') || 37777,
return { enableWebServer, webServerHost, webServerPort, webServerPath } webServerPath: picgo.getConfig<string>('settings.webServerPath') || defaultPath
}
} }
getServer (): http.Server { initServer (): void {
return http.createServer((req, res) => { this.server = http.createServer((req, res) => {
const requestPath = req.url?.split('?')[0] const requestPath = req.url?.split('?')[0]
const filePath = path.join(this.config.webServerPath, decodeURIComponent(requestPath as string)) const filePath = path.join(this.config.webServerPath, decodeURIComponent(requestPath || ''))
fs.stat(filePath, (err, stats) => {
if (err) {
res.writeHead(404)
res.end('404 Not Found')
return
}
try {
const stats = fs.statSync(filePath)
if (stats.isDirectory()) { if (stats.isDirectory()) {
fs.readdir(filePath, (err, files) => { serveDirectory(res, filePath, requestPath)
if (err) {
res.writeHead(500)
res.end('Error listing directory contents')
} else {
res.writeHead(200, { 'Content-Type': 'text/html' })
res.end(generateDirectoryListingHtml(files, requestPath))
}
})
} else { } else {
fs.readFile(filePath, (err, data) => { serveFile(res, filePath)
if (err) {
res.writeHead(404)
res.end('404 Not Found')
} else {
res.end(data)
}
})
} }
}) } catch (err) {
res.writeHead(404)
res.end('404 Not Found')
}
}) })
} }
start () { start () {
if (this.config.enableWebServer) { if (this.config.enableWebServer) {
this.server.listen(this.config.webServerPort, this.config.webServerHost, () => { this.server
logger.info(`Web server is running, http://${this.config.webServerHost}:${this.config.webServerPort}, root path is ${this.config.webServerPath}`) .listen(
}).on('error', (err) => { this.config.webServerPort === 36699 ? 37777 : this.config.webServerPort,
logger.error(err) 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 { } else {
logger.info('Web server is not enabled') logger.info('Web server is not enabled')
} }
} }
stop () { stop () {
this.server.close() this.server.close(() => {
logger.info('Web server is stopped') logger.info('Web server is stopped')
})
} }
restart () { restart () {
this.stop() this.stop()
this.config = this.getConfigWithDefaults() this.loadConfig()
this.server = this.getServer() this.initServer()
this.start() this.start()
} }
} }

View File

@ -52,3 +52,9 @@ export function safeSliceF (str:string, total: number) {
} }
return result return result
} }
export function encodeFilePath (filePath: string) {
filePath = filePath.replace(/\\/g, '/')
const parts = filePath.split('/')
return parts.map(encodeURIComponent).join('/')
}