feat: admin page proxy

This commit is contained in:
Innei
2021-09-19 15:04:19 +08:00
parent e815a4950d
commit e1e28edfb3
6 changed files with 61 additions and 10 deletions

View File

@@ -15,5 +15,8 @@
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"material-icon-theme.activeIconPack": "nest"
"material-icon-theme.activeIconPack": "nest",
"cSpell.words": [
"qaqdmin"
]
}

View File

@@ -27,7 +27,7 @@ type myError = {
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
private readonly logger = new Logger('捕获异常')
private readonly logger = new Logger(AllExceptionsFilter.name)
private readonly errorLogPipe: WriteStream
constructor(@Inject(REFLECTOR) private reflector: Reflector) {
this.errorLogPipe = fs.createWriteStream(resolve(LOGGER_DIR, 'error.log'), {

View File

@@ -1,10 +1,14 @@
import { Injectable, NestMiddleware } from '@nestjs/common'
import { Injectable, Logger, NestMiddleware } from '@nestjs/common'
import { IncomingMessage, ServerResponse } from 'http'
import { parseRelativeUrl } from '~/utils/ip.util'
// 用于屏蔽 PHP 的请求
@Injectable()
export class SecurityMiddleware implements NestMiddleware {
private logger: Logger
constructor() {
this.logger = new Logger(SecurityMiddleware.name)
}
async use(req: IncomingMessage, res: ServerResponse, next: () => void) {
// @ts-ignore
const url = parseRelativeUrl(req.originalUrl).pathname

View File

@@ -155,4 +155,15 @@ export class AdminExtraDto {
@IsString()
@IsOptional()
gaodemapKey?: string
@IsString()
@IsOptional()
title?: string
@IsBoolean()
@IsOptional()
/**
* 是否开启后台反代访问
*/
enableAdminProxy?: boolean
}

View File

@@ -51,12 +51,13 @@ export class ConfigsService {
this.logger = new Logger(ConfigsService.name)
}
private configInitd = false
public waitForConfigReady() {
// eslint-disable-next-line no-async-promise-executor
return new Promise<IConfig>(async (r, j) => {
return new Promise<Readonly<IConfig>>(async (r, j) => {
// 开始等待, 后续调用直接返回
if (this.configInitd) {
r(this.config)
r(this.getConfig())
return
}
@@ -64,7 +65,7 @@ export class ConfigsService {
let curCount = 0
do {
if (this.configInitd) {
r({ ...this.config })
r(this.getConfig())
return
}
await sleep(100)

View File

@@ -1,14 +1,46 @@
import { Controller, Get, Header } from '@nestjs/common'
import { HttpCache } from '~/common/decorator/cache.decorator'
import { HTTPDecorators } from '~/common/decorator/http.decorator'
import { ApiName } from '~/common/decorator/openapi.decorator'
import { ConfigsService } from '../configs/configs.service'
@Controller()
interface IInjectableData {
BASE_API: null | string
WEB_URL: null | string
GATEWAY: null | string
LOGIN_BG: null | string
TITLE: null | string
}
@Controller('/')
@ApiName
export class PageProxyController {
@Get('/admin')
constructor(private readonly configs: ConfigsService) {}
@Get('/qaqdmin')
@Header('Content-Type', 'text/html')
@HTTPDecorators.Bypass
proxyAdmin() {
return ''
@HttpCache({ disable: true })
async proxyAdmin() {
const {
adminExtra,
url: { wsUrl, serverUrl, webUrl },
} = await this.configs.waitForConfigReady()
if (!adminExtra.enableAdminProxy) {
return '<h1>Admin Proxy is disabled</h1>'
}
const indexEntryUrl = `https://cdn.jsdelivr.net/gh/mx-space/admin-next@gh-pages/index.html`
let entry = await (await fetch(indexEntryUrl)).text()
entry = entry.replace(
`<!-- injectable script -->`,
`<script>${`window.injectData = ${JSON.stringify({
BASE_API: serverUrl,
GATEWAY: wsUrl,
LOGIN_BG: adminExtra.background,
TITLE: adminExtra.title,
WEB_URL: webUrl,
} as IInjectableData)}`}</script>`,
)
return entry
}
}