Skip to content

Commit

Permalink
✨ Feature(custom): add buildin web server
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #180
  • Loading branch information
Kuingsmile committed Apr 2, 2024
1 parent 8ed24cb commit ab8b62e
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 2 deletions.
3 changes: 3 additions & 0 deletions public/i18n/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,12 @@ SETTINGS_ENABLE_SERVER: Enable Server
SETTINGS_SET_SERVER_HOST: Set Server Host
SETTINGS_SET_SERVER_PORT: Set Server Port
SETTINGS_SET_SERVER_KEY: Set Auth Key
SETTINGS_SET_WEB_SERVER: Set Web Server
SETTINGS_TIPS_WEB_SERVER_NOTICE: If you don't know what is the web server's function, please read the document, or don't modify the configuration.
SETTINGS_SET_ENABLE_WEB_SERVER: Enable Web Server
SETTINGS_SET_WEB_SERVER_HOST: Set Web Server Host
SETTINGS_SET_WEB_SERVER_PORT: Set Web Server Port
SETTINGS_SET_WEB_SERVER_PATH: Set Web Server Path
SETTINGS_TIP_PLACEHOLDER_WEB_HOST: Default:127.0.0.1
SETTINGS_TIP_PLACEHOLDER_WEB_PORT: Default:37777
SETTINGS_TIP_PLACEHOLDER_HOST: Default:127.0.0.1
Expand Down
3 changes: 3 additions & 0 deletions public/i18n/zh-CN.yml
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,12 @@ SETTINGS_ENABLE_SERVER: 是否开启Server
SETTINGS_SET_SERVER_HOST: 设置监听地址
SETTINGS_SET_SERVER_PORT: 设置监听端口
SETTINGS_SET_SERVER_KEY: 设置鉴权密钥
SETTINGS_SET_WEB_SERVER: 设置Web服务
SETTINGS_TIPS_WEB_SERVER_NOTICE: 如果你不知道Web服务的作用,请阅读文档,或者不用修改配置。
SETTINGS_SET_ENABLE_WEB_SERVER: 是否开启Web服务
SETTINGS_SET_WEB_SERVER_HOST: 设置Web服务监听地址
SETTINGS_SET_WEB_SERVER_PORT: 设置Web服务监听端口
SETTINGS_SET_WEB_SERVER_PATH: 设置Web服务路径
SETTINGS_TIP_PLACEHOLDER_WEB_HOST: 推荐默认地址:127.0.0.1
SETTINGS_TIP_PLACEHOLDER_WEB_PORT: 推荐默认端口:37777
SETTINGS_TIP_PLACEHOLDER_HOST: 推荐默认地址:127.0.0.1
Expand Down
3 changes: 3 additions & 0 deletions public/i18n/zh-TW.yml
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,12 @@ SETTINGS_ENABLE_SERVER: 是否開啟Server
SETTINGS_SET_SERVER_HOST: 設定監聽地址
SETTINGS_SET_SERVER_PORT: 設定監聽端口
SETTINGS_SET_SERVER_KEY: 設定鑒權密鑰
SETTINGS_SET_WEB_SERVER: 設定Web服務
SETTINGS_TIPS_WEB_SERVER_NOTICE: 如果你不知道Web服務的作用,請閱讀文檔,或者不用修改設定。
SETTINGS_SET_ENABLE_WEB_SERVER: 是否開啟Web服務
SETTINGS_SET_WEB_SERVER_HOST: 設定Web服務地
SETTINGS_SET_WEB_SERVER_PORT: 設定Web服務端口
SETTINGS_SET_WEB_SERVER_PATH: 設定Web服務路徑
SETTINGS_TIP_PLACEHOLDER_WEB_HOST: 推薦預設地址:127.0.0.1
SETTINGS_TIP_PLACEHOLDER_WEB_PORT: 推薦預設端口:37777
SETTINGS_TIP_PLACEHOLDER_HOST: 推薦預設地址:127.0.0.1
Expand Down
7 changes: 7 additions & 0 deletions src/main/events/ipcList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import SSHClient from '../utils/sshClient'
import { ISftpPlistConfig } from 'piclist'

import { removeFileFromS3InMain, removeFileFromDogeInMain, removeFileFromHuaweiInMain } from '~/main/utils/deleteFunc'
import webServer from '../server/webServer'

const STORE_PATH = app.getPath('userData')

Expand Down Expand Up @@ -360,6 +361,12 @@ export default {
ipcMain.on('updateServer', () => {
server.restart()
})
ipcMain.on('stopWebServer', () => {
webServer.stop()
})
ipcMain.on('restartWebServer', () => {
webServer.restart()
})
ipcMain.on(OPEN_DEVTOOLS, (event: IpcMainEvent) => {
event.sender.openDevTools()
})
Expand Down
2 changes: 2 additions & 0 deletions src/main/lifeCycle/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import path from 'path'
import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static'
import fs from 'fs-extra'
import { startFileServer } from '../fileServer'
import webServer from '../server/webServer'
import axios from 'axios'
const isDevelopment = process.env.NODE_ENV !== 'production'

Expand Down Expand Up @@ -179,6 +180,7 @@ class LifeCycle {
})
server.startup()
startFileServer()
webServer.start()
if (process.env.NODE_ENV !== 'development') {
handleStartUpFiles(process.argv, process.cwd())
}
Expand Down
96 changes: 96 additions & 0 deletions src/main/server/webServer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import http from 'http'
import fs from 'fs-extra'
import path from 'path'
import picgo from '@core/picgo'
import logger from '../../apis/core/picgo/logger'

const defaultPath = process.platform === 'win32' ? 'C:/Users/' : '/'

function generateDirectoryListingHtml (files: any[], requestPath: any) {
let html = '<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body><h1>Directory Listing</h1><ul>'
files.forEach((file: string) => {
html += `<li><a href="${path.join(requestPath, file)}">${file}</a></li>`
})
html += '</ul></body></html>'
return html
}

class WebServer {
private server: http.Server
private config: IStringKeyMap

constructor () {
this.config = this.getConfigWithDefaults()
this.server = this.getServer()
}

getConfigWithDefaults (): IStringKeyMap {
const enableWebServer = picgo.getConfig<boolean>('settings.enableWebServer') || false
const webServerHost = picgo.getConfig<string>('settings.webServerHost') || '0.0.0.0'
const webServerPort = picgo.getConfig<number>('settings.webServerPort') || 37777
const webServerPath = picgo.getConfig<string>('settings.webServerPath') || defaultPath
return { enableWebServer, webServerHost, webServerPort, webServerPath }
}

getServer (): http.Server {
return 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
}

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))
}
})
} else {
fs.readFile(filePath, (err, data) => {
if (err) {
res.writeHead(404)
res.end('404 Not Found')
} else {
res.end(data)
}
})
}
})
})
}

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)
})
} else {
logger.info('Web server is not enabled')
}
}

stop () {
this.server.close()
logger.info('Web server is stopped')
}

restart () {
this.stop()
this.config = this.getConfigWithDefaults()
this.server = this.getServer()
this.start()
}
}

export default new WebServer()
119 changes: 118 additions & 1 deletion src/renderer/pages/PicGoSetting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,18 @@
{{ $T('SETTINGS_CLICK_TO_SET') }}
</el-button>
</el-form-item>
<el-form-item
:label="$T('SETTINGS_SET_WEB_SERVER')"
>
<el-button
type="primary"
round
size="small"
@click="webServerVisible = true"
>
{{ $T('SETTINGS_CLICK_TO_SET') }}
</el-button>
</el-form-item>
<el-form-item
:label="$T('SETTINGS_SET_SERVER')"
>
Expand Down Expand Up @@ -732,6 +744,7 @@
:title="$T('SETTINGS_CUSTOM_LINK_FORMAT')"
:modal-append-to-body="false"
center
draggable
append-to-body
>
<el-form
Expand Down Expand Up @@ -783,6 +796,7 @@
:modal-append-to-body="false"
width="70%"
center
draggable
append-to-body
>
<el-form
Expand Down Expand Up @@ -840,6 +854,7 @@
:modal-append-to-body="false"
width="70%"
center
draggable
append-to-body
>
<el-form
Expand Down Expand Up @@ -896,6 +911,7 @@
:title="$T('SETTINGS_CHECK_UPDATE')"
:modal-append-to-body="false"
center
draggable
append-to-body
>
<div>
Expand Down Expand Up @@ -1025,6 +1041,7 @@
:modal-append-to-body="false"
width="500px"
center
draggable
append-to-body
>
<el-form
Expand Down Expand Up @@ -1122,6 +1139,7 @@
:title="$T('SETTINGS_SET_PICGO_SERVER')"
:modal-append-to-body="false"
center
draggable
append-to-body
>
<div class="notice-text">
Expand Down Expand Up @@ -1187,13 +1205,77 @@
</el-button>
</template>
</el-dialog>
<el-dialog
v-model="webServerVisible"
class="server-dialog"
width="60%"
:title="$T('SETTINGS_SET_WEB_SERVER')"
:modal-append-to-body="false"
align-center
draggable
append-to-body
@close="confirmWebServerSetting"
>
<div class="notice-text">
{{ $T('SETTINGS_TIPS_WEB_SERVER_NOTICE') }}
</div>
<el-form
label-position="right"
label-width="180px"
>
<el-form-item
:label="$T('SETTINGS_SET_ENABLE_WEB_SERVER')"
>
<el-switch
v-model="form.enableWebServer"
:active-text="$T('SETTINGS_OPEN')"
:inactive-text="$T('SETTINGS_CLOSE')"
@change="handleEnableWebServerChange"
/>
</el-form-item>
<template v-if="form.enableWebServer">
<el-form-item
:label="$T('SETTINGS_SET_WEB_SERVER_HOST')"
>
<el-input
v-model="form.webServerHost"
type="input"
:placeholder="$T('SETTINGS_TIP_PLACEHOLDER_WEB_HOST')"
@change="handleWebServerHostChange"
/>
</el-form-item>
<el-form-item
:label="$T('SETTINGS_SET_WEB_SERVER_PORT')"
>
<el-input-number
v-model="form.webServerPort"
:min="1"
:max="65535"
:placeholder="$T('SETTINGS_TIP_PLACEHOLDER_WEB_PORT')"
@change="handleWebServerPortChange"
/>
</el-form-item>
<el-form-item
:label="$T('SETTINGS_SET_WEB_SERVER_PATH')"
>
<el-input
v-model="form.webServerPath"
type="input"
:placeholder="$T('SETTINGS_SET_WEB_SERVER_PATH')"
@change="handleWebServerPathChange"
/>
</el-form-item>
</template>
</el-form>
</el-dialog>
<el-dialog
v-model="syncVisible"
class="server-dialog"
width="60%"
:title="$T('SETTINGS_SYNC_CONFIG_TITLE')"
:modal-append-to-body="false"
center
draggable
append-to-body
>
<div class="notice-text">
Expand Down Expand Up @@ -1300,6 +1382,7 @@
:title="$T('SETTINGS_UP_DOWN_DESC')"
:modal-append-to-body="false"
center
draggable
append-to-body
>
<el-form
Expand Down Expand Up @@ -1871,7 +1954,11 @@ const form = reactive<ISettingForm>({
deleteLocalFile: false,
serverKey: '',
aesPassword: '',
manualPageOpen: 'browser'
manualPageOpen: 'browser',
enableWebServer: false,
webServerHost: '0.0.0.0',
webServerPort: 37777,
webServerPath: ''
})
const languageList = i18nManager.languageList.map(item => ({
Expand All @@ -1888,6 +1975,7 @@ const logFileVisible = ref(false)
const customLinkVisible = ref(false)
const checkUpdateVisible = ref(false)
const serverVisible = ref(false)
const webServerVisible = ref(false)
const syncVisible = ref(false)
const upDownConfigVisible = ref(false)
const proxyVisible = ref(false)
Expand Down Expand Up @@ -2039,6 +2127,10 @@ async function initData () {
form.serverKey = settings.serverKey || ''
form.aesPassword = settings.aesPassword || 'PicList-aesPassword'
form.manualPageOpen = settings.manualPageOpen || 'window'
form.enableWebServer = settings.enableWebServer || false
form.webServerHost = settings.webServerHost || '0.0.0.0'
form.webServerPort = settings.webServerPort || 37777
form.webServerPath = settings.webServerPath || ''
currentLanguage.value = settings.language ?? 'zh-CN'
currentStartMode.value = settings.startMode || 'quiet'
customLink.value = settings.customLink || '![$fileName]($url)'
Expand Down Expand Up @@ -2296,6 +2388,31 @@ function cancelCheckVersion () {
checkUpdateVisible.value = false
}
function handleEnableWebServerChange (val: ICheckBoxValueType) {
saveConfig('settings.enableWebServer', val)
}
function handleWebServerHostChange (val: string) {
saveConfig('settings.webServerHost', val)
}
function handleWebServerPortChange (val?: number, oldVal?: number) {
saveConfig('settings.webServerPort', Number(val) || 37777)
}
function handleWebServerPathChange (val: string) {
saveConfig('settings.webServerPath', val)
}
function confirmWebServerSetting () {
console.log('confirmWebServerSetting')
if (form.enableWebServer) {
sendToMain('restartWebServer')
} else {
sendToMain('stopWebServer')
}
}
function handleServerKeyChange (val: string) {
saveConfig('settings.serverKey', val)
}
Expand Down
Loading

0 comments on commit ab8b62e

Please sign in to comment.