mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 10:25:52 +02:00
refactor: nginx conf parser #45
This commit is contained in:
parent
b7d5590714
commit
5cc9068f5f
27 changed files with 942 additions and 1040 deletions
|
@ -91,12 +91,16 @@ Nginx 网络管理界面,由 [0xJacky](https://jackyu.cn/) 与 [Hintay](https
|
|||
我们欢迎您将项目翻译成任何语言。
|
||||
|
||||
### 构建基于
|
||||
|
||||
- [The Go Programming Language](https://go.dev/)
|
||||
- [The Go Programming Language](https://go.dev)
|
||||
- [Gin Web Framework](https://gin-gonic.com)
|
||||
- [GORM](http://gorm.io/index.html)
|
||||
- [Vue 2](https://vuejs.org)
|
||||
- [vue-gettext](https://github.com/Polyconseil/vue-gettext)
|
||||
- [GORM](http://gorm.io)
|
||||
- [Vue 3](https://v3.vuejs.org)
|
||||
- [Vite](https://vitejs.dev)
|
||||
- [TypeScript](https://www.typescriptlang.org/)
|
||||
- [Ant Design Vue](https://antdv.com)
|
||||
- [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
|
||||
- [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
|
||||
- [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
|
||||
|
||||
## 入门指南
|
||||
|
||||
|
|
|
@ -93,12 +93,16 @@ Nginx 網路管理介面,由 [0xJacky](https://jackyu.cn/) 與 [Hintay](https
|
|||
我們歡迎您將專案翻譯成任何語言。
|
||||
|
||||
### 構建基於
|
||||
|
||||
- [The Go Programming Language](https://go.dev/)
|
||||
- [The Go Programming Language](https://go.dev)
|
||||
- [Gin Web Framework](https://gin-gonic.com)
|
||||
- [GORM](http://gorm.io/index.html)
|
||||
- [Vue 2](https://vuejs.org)
|
||||
- [vue-gettext](https://github.com/Polyconseil/vue-gettext)
|
||||
- [GORM](http://gorm.io)
|
||||
- [Vue 3](https://v3.vuejs.org)
|
||||
- [Vite](https://vitejs.dev)
|
||||
- [TypeScript](https://www.typescriptlang.org/)
|
||||
- [Ant Design Vue](https://antdv.com)
|
||||
- [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
|
||||
- [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
|
||||
- [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
|
||||
|
||||
## 入門指南
|
||||
|
||||
|
|
|
@ -99,6 +99,7 @@ We welcome translations into any language.
|
|||
- [Ant Design Vue](https://antdv.com)
|
||||
- [vue3-gettext](https://github.com/jshmrtn/vue3-gettext)
|
||||
- [vue3-ace-editor](https://github.com/CarterLi/vue3-ace-editor)
|
||||
- [Gonginx](https://github.com/tufanbarisyildirim/gonginx)
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
"less": "^4.1.3",
|
||||
"typescript": "^4.6.4",
|
||||
"unplugin-vue-components": "^0.22.9",
|
||||
"vite": "^3.2.3",
|
||||
"vite": "^4.0.3",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vue-tsc": "^1.0.9"
|
||||
}
|
||||
|
|
|
@ -74,16 +74,6 @@ export const routes = [
|
|||
hideChildren: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'config/:dir*',
|
||||
name: () => $gettext('Manage Configs'),
|
||||
component: () => import('@/views/config/Config.vue'),
|
||||
meta: {
|
||||
icon: FileOutlined,
|
||||
hideChildren: true,
|
||||
hiddenInSidebar: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'config/:name+/edit',
|
||||
name: () => $gettext('Edit Configuration'),
|
||||
|
|
|
@ -18,7 +18,7 @@ const table = ref(null)
|
|||
const route = useRoute()
|
||||
|
||||
const basePath = computed(() => {
|
||||
let dir = route?.params?.dir ? (route?.params?.dir as string[])?.join('/') : ''
|
||||
let dir = route?.query?.dir ?? ''
|
||||
if (dir) dir += '/'
|
||||
return dir
|
||||
})
|
||||
|
@ -54,7 +54,9 @@ watch(get_params, () => {
|
|||
})
|
||||
} else {
|
||||
$router.push({
|
||||
path: '/config/' + basePath + r
|
||||
query: {
|
||||
dir: basePath + r
|
||||
}
|
||||
})
|
||||
}
|
||||
}"
|
||||
|
|
|
@ -30,7 +30,7 @@ const columns = [{
|
|||
template.push(<Badge status="success"/>)
|
||||
template.push($gettext('Enabled'))
|
||||
} else {
|
||||
template.push(<Badge status="error"/>)
|
||||
template.push(<Badge status="warning"/>)
|
||||
template.push($gettext('Disabled'))
|
||||
}
|
||||
return h('div', template)
|
||||
|
|
|
@ -129,7 +129,7 @@ const issue_cert = async (server_name: string, callback: Function) => {
|
|||
}
|
||||
|
||||
const no_server_name = computed(() => {
|
||||
return props.directivesMap['server_name'].length === 0
|
||||
return props.directivesMap['server_name']?.length === 0
|
||||
})
|
||||
|
||||
const name = computed(() => {
|
||||
|
|
|
@ -24,8 +24,8 @@ function add() {
|
|||
|
||||
function save() {
|
||||
adding.value = false
|
||||
if (mode.value === If) {
|
||||
directive.directive = If
|
||||
if (mode.value === 'multi-line') {
|
||||
directive.directive = ''
|
||||
}
|
||||
|
||||
if (props.idx) {
|
||||
|
@ -42,19 +42,19 @@ function save() {
|
|||
<div>
|
||||
<div class="add-directive-temp" v-if="adding">
|
||||
<a-form-item>
|
||||
<a-select v-model:value="mode" default-value="default" style="width: 150px">
|
||||
<a-select v-model:value="mode" default-value="default" style="width: 180px">
|
||||
<a-select-option value="default">
|
||||
{{ $gettext('Single Directive') }}
|
||||
</a-select-option>
|
||||
<a-select-option value="if">
|
||||
if
|
||||
<a-select-option value="multi-line">
|
||||
{{ $gettext('Multi-line Directive') }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
|
||||
<div class="input-wrapper">
|
||||
<code-editor v-if="mode===If" default-height="100px" style="width: 100%;"
|
||||
<code-editor v-if="mode==='multi-line'" default-height="100px" style="width: 100%;"
|
||||
v-model:content="directive.params"/>
|
||||
<a-input-group v-else compact>
|
||||
<a-input style="width: 30%" :placeholder="$gettext('Directive')"
|
||||
|
@ -73,7 +73,9 @@ function save() {
|
|||
</div>
|
||||
<a-button block v-if="!adding" @click="add">{{ $gettext('Add Directive Below') }}</a-button>
|
||||
<a-button type="primary" v-else block @click="save"
|
||||
:disabled="!directive.directive||!directive.params">{{ $gettext('Save Directive') }}
|
||||
:disabled="(mode==='default'&&(!directive.directive||!directive.params))
|
||||
||(!directive.params&&mode==='multi-line')">
|
||||
{{ $gettext('Save Directive') }}
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -32,7 +32,7 @@ function onSave(idx: number) {
|
|||
item-key="name"
|
||||
class="list-group"
|
||||
ghost-class="ghost"
|
||||
handle=".ant-input-group-addon"
|
||||
handle=".anticon-holder"
|
||||
>
|
||||
<template #item="{ element: directive, index }">
|
||||
<directive-editor-item @click="current_idx=index"
|
||||
|
|
|
@ -42,8 +42,11 @@ function save() {
|
|||
<template>
|
||||
<div class="dir-editor-item">
|
||||
<div class="input-wrapper">
|
||||
<code-editor v-if="directive.directive === If" v-model:content="directive.params"
|
||||
defaultHeight="100px" style="width: 100%;"/>
|
||||
<div class="code-editor-wrapper" v-if="directive.directive === ''">
|
||||
<HolderOutlined style="padding: 5px"/>
|
||||
<code-editor v-model:content="directive.params"
|
||||
defaultHeight="100px" style="width: 100%;"/>
|
||||
</div>
|
||||
|
||||
<a-input v-else
|
||||
v-model:value="directive.params" @click="current_idx=index">
|
||||
|
@ -91,6 +94,16 @@ function save() {
|
|||
margin: 15px 0;
|
||||
}
|
||||
|
||||
.code-editor-wrapper {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.anticon-holder {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.directive-editor-extra {
|
||||
background-color: #fafafa;
|
||||
padding: 10px 20px;
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":"1.7.0","build_id":63,"total_build":133}
|
||||
{"version":"1.7.0","build_id":0,"total_build":0}
|
|
@ -361,20 +361,120 @@
|
|||
resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz#75b4c27948c81e88ccd3a8902047bcd797f38d32"
|
||||
integrity sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==
|
||||
|
||||
"@esbuild/android-arm@0.15.13":
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.15.13.tgz#ce11237a13ee76d5eae3908e47ba4ddd380af86a"
|
||||
integrity sha512-RY2fVI8O0iFUNvZirXaQ1vMvK0xhCcl0gqRj74Z6yEiO1zAUa7hbsdwZM1kzqbxHK7LFyMizipfXT3JME+12Hw==
|
||||
"@esbuild/android-arm64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.16.13.tgz#1fc9bfbff0bac558008b2ad7242db1c8024d8cfd"
|
||||
integrity sha512-r4xetsd1ez1NF9/9R2f9Q6AlxqiZLwUqo7ICOcvEVwopVkXUcspIjEbJk0EVTgT6Cp5+ymzGPT6YNV0ievx4yA==
|
||||
|
||||
"@esbuild/android-arm@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.16.13.tgz#df3317286eed68c727daf39c2d585625f9c2f170"
|
||||
integrity sha512-JmtqThupn9Yf+FzANE+GG73ASUkssnPwOsndUElhp23685QzRK+MO1UompOlBaXV9D5FTuYcPnw7p4mCq2YbZQ==
|
||||
|
||||
"@esbuild/android-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.16.13.tgz#c34826c4bdc57c60cbfb8d5bbd2306a89225626a"
|
||||
integrity sha512-hKt1bFht/Vtp0xJ0ZVzFMnPy1y1ycmM3KNnp3zsyZfQmw7nhs2WLO4vxdR5YG+6RsHKCb2zbZ3VwlC0Tij0qyA==
|
||||
|
||||
"@esbuild/darwin-arm64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.16.13.tgz#0b80c8580c262ccfb1203053201cf19c6f7b4cdb"
|
||||
integrity sha512-ogrVuNi2URocrr3Ps20f075EMm9V7IeenOi9FRj4qdbT6mQlwLuP4l90PW2iBrKERx0oRkcZprEUNsz/3xd7ww==
|
||||
|
||||
"@esbuild/darwin-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.16.13.tgz#f1a6c9ea67d4eaaf4944e1cbceb800eabc6e7e74"
|
||||
integrity sha512-Agajik9SBGiKD7FPXE+ExW6x3MgA/dUdpZnXa9y1tyfE4lKQx+eQiknSdrBnWPeqa9wL0AOvkhghmYhpVkyqkA==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.13.tgz#d1a45ac5c4a1be566c4eefbadbe5a967288ad338"
|
||||
integrity sha512-KxMO3/XihBcHM+xQUM6nQZO1SgQuOsd1DCnKF1a4SIf/i5VD45vrqN3k8ePgFrEbMi7m5JeGmvNqwJXinF0a4Q==
|
||||
|
||||
"@esbuild/freebsd-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.16.13.tgz#ec64a31cabb08343bb4520a221324b40509dffc8"
|
||||
integrity sha512-Ez15oqV1vwvZ30cVLeBW14BsWq/fdWNQGMOxxqaSJVQVLqHhvgfQ7gxGDiN9tpJdeQhqJO+Q0r02/Tce5+USNg==
|
||||
|
||||
"@esbuild/linux-arm64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.16.13.tgz#e8db3c3751b32ecf801751424eae43f6863a2ee7"
|
||||
integrity sha512-qi5n7KwcGViyJeZeQnu8fB6dC3Mlm5PGaqSv2HhQDDx/MPvVfQGNMcv7zcBL4qk3FkuWhGVwXkjQ76x7R0PWlA==
|
||||
|
||||
"@esbuild/linux-arm@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.16.13.tgz#ac0c8e9f3db8d418f588ae250e9c66ffdcf3cd82"
|
||||
integrity sha512-18dLd2L3mda+iFj6sswyBMSh2UwniamD9M4DwPv8VM+9apRFlQ5IGKxBdumnTuOI4NvwwAernmUseWhYQ9k+rg==
|
||||
|
||||
"@esbuild/linux-ia32@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.16.13.tgz#41ee9bd3b7161ab681fab6cb3990a3f5c08a9940"
|
||||
integrity sha512-2489Xad9sr+6GD7nB913fUqpCsSwVwgskkQTq4Or2mZntSPYPebyJm8l1YruHo7oqYMTGV6RiwGE4gRo3H+EPQ==
|
||||
|
||||
"@esbuild/linux-loong64@0.14.53":
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.14.53.tgz#251b4cd6760fadb4d68a05815e6dc5e432d69cd6"
|
||||
integrity sha512-W2dAL6Bnyn4xa/QRSU3ilIK4EzD5wgYXKXJiS1HDF5vU3675qc2bvFyLwbUcdmssDveyndy7FbitrCoiV/eMLg==
|
||||
|
||||
"@esbuild/linux-loong64@0.15.13":
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.13.tgz#64e8825bf0ce769dac94ee39d92ebe6272020dfc"
|
||||
integrity sha512-+BoyIm4I8uJmH/QDIH0fu7MG0AEx9OXEDXnqptXCwKOlOqZiS4iraH1Nr7/ObLMokW3sOCeBNyD68ATcV9b9Ag==
|
||||
"@esbuild/linux-loong64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.16.13.tgz#e4a832708e0b47078b91413edcfdb6af88c854a3"
|
||||
integrity sha512-x8KplRu9Y43Px8I9YS+sPBwQ+fw44Mvp2BPVADopKDWz+h3fcj1BvRU58kxb89WObmwKX9sWdtYzepL4Fmx03A==
|
||||
|
||||
"@esbuild/linux-mips64el@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.16.13.tgz#30d8571b71e0b8bf25fc5ef11422221ed23cdacc"
|
||||
integrity sha512-qhhdWph9FLwD9rVVC/nUf7k2U4NZIA6/mGx0B7+O6PFV0GjmPA2E3zDQ4NUjq9P26E0DeAZy9akH9dYcUBRU7A==
|
||||
|
||||
"@esbuild/linux-ppc64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.16.13.tgz#32a3855d4b79ba1d2b63dab592cb9f0d4a9ba485"
|
||||
integrity sha512-cVWAPKsrRVxI1jCeJHnYSbE3BrEU+pZTZK2gfao9HRxuc+3m4+RLfs3EVEpGLmMKEcWfVCB9wZ3yNxnknutGKQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.16.13.tgz#6139202858da8202724d7079102614c269524f34"
|
||||
integrity sha512-Agb7dbRyZWnmPn5Vvf0eyqaEUqSsaIUwwyInu2EoFTaIDRp093QU2M5alUyOooMLkRbD1WvqQNwx08Z/g+SAcQ==
|
||||
|
||||
"@esbuild/linux-s390x@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.16.13.tgz#df3550a51e4155cde31486e01d8121f078e959ae"
|
||||
integrity sha512-AqRBIrc/+kl08ahliNG+EyU+j41wIzQfwBTKpi80cCDiYvYFPuXjvzZsD9muiu58Isj0RVni9VgC4xK/AnSW4g==
|
||||
|
||||
"@esbuild/linux-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.16.13.tgz#deb7951829ea5930e0d88440aeb5df0756ebb2d0"
|
||||
integrity sha512-S4wn2BimuhPcoArRtVrdHUKIymCCZcYAXQE47kUiX4yrUrEX2/ifn5eKNbZ5c1jJKUlh1gC2ESIN+iw3wQax3g==
|
||||
|
||||
"@esbuild/netbsd-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.16.13.tgz#8cba08074263862138cc5c63ad7f9640fe3faa69"
|
||||
integrity sha512-2c8JWgfUMlQHTdaR5X3xNMwqOyad8kgeCupuVkdm3QkUOzGREjlTETQsK6oHifocYzDCo9FeKcUwsK356SdR+g==
|
||||
|
||||
"@esbuild/openbsd-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.16.13.tgz#4ae19ac63c665424d248ba5c577618dd7bbcebd5"
|
||||
integrity sha512-Bwh+PmKD/LK+xBjqIpnYnKYj0fIyQJ0YpRxsn0F+WfzvQ2OA+GKDlf8AHosiCns26Q4Dje388jQVwfOBZ1GaFw==
|
||||
|
||||
"@esbuild/sunos-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.16.13.tgz#592caacab6b2c7669cd869b51f66dc354da03fc2"
|
||||
integrity sha512-8wwk6f9XGnhrF94/DBdFM4Xm1JeCyGTCj67r516VS9yvBVQf3Rar54L+XPVDs/oZOokwH+XsktrgkuTMAmjntg==
|
||||
|
||||
"@esbuild/win32-arm64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.16.13.tgz#965ebbe889e4221962250c55facaa1e48130c162"
|
||||
integrity sha512-Jmwbp/5ArLCiRAHC33ODfcrlIcbP/exXkOEUVkADNJC4e/so2jm+i8IQFvVX/lA2GWvK3GdgcN0VFfp9YITAbg==
|
||||
|
||||
"@esbuild/win32-ia32@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.16.13.tgz#1b04965bcf340ba4879b452ac32df63216d4c87e"
|
||||
integrity sha512-AX6WjntGjhJHzrPSVvjMD7grxt41koHfAOx6lxLorrpDwwIKKPaGDASPZgvFIZHTbwhOtILW6vAXxYPDsKpDJA==
|
||||
|
||||
"@esbuild/win32-x64@0.16.13":
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.16.13.tgz#0b0989cf0e7887cb0f3124e705cee68a694b96dd"
|
||||
integrity sha512-A+U4gM6OOkPS03UgVU08GTpAAAxPsP/8Z4FmneGo4TaVSD99bK9gVJXlqUEPMO/htFXEAht2O6pX4ErtLY5tVg==
|
||||
|
||||
"@jridgewell/gen-mapping@^0.1.0":
|
||||
version "0.1.1"
|
||||
|
@ -1442,201 +1542,101 @@ esbuild-android-64@0.14.53:
|
|||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz#259bc3ef1399a3cad8f4f67c40ee20779c4de675"
|
||||
integrity sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==
|
||||
|
||||
esbuild-android-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.15.13.tgz#5f25864055dbd62e250f360b38b4c382224063af"
|
||||
integrity sha512-yRorukXBlokwTip+Sy4MYskLhJsO0Kn0/Fj43s1krVblfwP+hMD37a4Wmg139GEsMLl+vh8WXp2mq/cTA9J97g==
|
||||
|
||||
esbuild-android-arm64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.53.tgz#2158253d4e8f9fdd2a081bbb4f73b8806178841e"
|
||||
integrity sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==
|
||||
|
||||
esbuild-android-arm64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.15.13.tgz#d8820f999314efbe8e0f050653a99ff2da632b0f"
|
||||
integrity sha512-TKzyymLD6PiVeyYa4c5wdPw87BeAiTXNtK6amWUcXZxkV51gOk5u5qzmDaYSwiWeecSNHamFsaFjLoi32QR5/w==
|
||||
|
||||
esbuild-darwin-64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.53.tgz#b4681831fd8f8d06feb5048acbe90d742074cc2a"
|
||||
integrity sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==
|
||||
|
||||
esbuild-darwin-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.15.13.tgz#99ae7fdaa43947b06cd9d1a1c3c2c9f245d81fd0"
|
||||
integrity sha512-WAx7c2DaOS6CrRcoYCgXgkXDliLnFv3pQLV6GeW1YcGEZq2Gnl8s9Pg7ahValZkpOa0iE/ojRVQ87sbUhF1Cbg==
|
||||
|
||||
esbuild-darwin-arm64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.53.tgz#d267d957852d121b261b3f76ead86e5b5463acc9"
|
||||
integrity sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==
|
||||
|
||||
esbuild-darwin-arm64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.13.tgz#bafa1814354ad1a47adcad73de416130ef7f55e3"
|
||||
integrity sha512-U6jFsPfSSxC3V1CLiQqwvDuj3GGrtQNB3P3nNC3+q99EKf94UGpsG9l4CQ83zBs1NHrk1rtCSYT0+KfK5LsD8A==
|
||||
|
||||
esbuild-freebsd-64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.53.tgz#aca2af6d72b537fe66a38eb8f374fb66d4c98ca0"
|
||||
integrity sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==
|
||||
|
||||
esbuild-freebsd-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.13.tgz#84ef85535c5cc38b627d1c5115623b088d1de161"
|
||||
integrity sha512-whItJgDiOXaDG/idy75qqevIpZjnReZkMGCgQaBWZuKHoElDJC1rh7MpoUgupMcdfOd+PgdEwNQW9DAE6i8wyA==
|
||||
|
||||
esbuild-freebsd-arm64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.53.tgz#76282e19312d914c34343c8a7da6cc5f051580b9"
|
||||
integrity sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==
|
||||
|
||||
esbuild-freebsd-arm64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.13.tgz#033f21de434ec8e0c478054b119af8056763c2d8"
|
||||
integrity sha512-6pCSWt8mLUbPtygv7cufV0sZLeylaMwS5Fznj6Rsx9G2AJJsAjQ9ifA+0rQEIg7DwJmi9it+WjzNTEAzzdoM3Q==
|
||||
|
||||
esbuild-linux-32@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.53.tgz#1045d34cf7c5faaf2af3b29cc1573b06580c37e5"
|
||||
integrity sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==
|
||||
|
||||
esbuild-linux-32@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.15.13.tgz#54290ea8035cba0faf1791ce9ae6693005512535"
|
||||
integrity sha512-VbZdWOEdrJiYApm2kkxoTOgsoCO1krBZ3quHdYk3g3ivWaMwNIVPIfEE0f0XQQ0u5pJtBsnk2/7OPiCFIPOe/w==
|
||||
|
||||
esbuild-linux-64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz#ab3f2ee2ebb5a6930c72d9539cb34b428808cbe4"
|
||||
integrity sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==
|
||||
|
||||
esbuild-linux-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.15.13.tgz#4264249281ea388ead948614b57fb1ddf7779a2c"
|
||||
integrity sha512-rXmnArVNio6yANSqDQlIO4WiP+Cv7+9EuAHNnag7rByAqFVuRusLbGi2697A5dFPNXoO//IiogVwi3AdcfPC6A==
|
||||
|
||||
esbuild-linux-arm64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.53.tgz#1f5530412f6690949e78297122350488d3266cfe"
|
||||
integrity sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==
|
||||
|
||||
esbuild-linux-arm64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.13.tgz#9323c333924f97a02bdd2ae8912b36298acb312d"
|
||||
integrity sha512-alEMGU4Z+d17U7KQQw2IV8tQycO6T+rOrgW8OS22Ua25x6kHxoG6Ngry6Aq6uranC+pNWNMB6aHFPh7aTQdORQ==
|
||||
|
||||
esbuild-linux-arm@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz#a44ec9b5b42007ab6c0d65a224ccc6bbd97c54cf"
|
||||
integrity sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==
|
||||
|
||||
esbuild-linux-arm@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.15.13.tgz#b407f47b3ae721fe4e00e19e9f19289bef87a111"
|
||||
integrity sha512-Ac6LpfmJO8WhCMQmO253xX2IU2B3wPDbl4IvR0hnqcPrdfCaUa2j/lLMGTjmQ4W5JsJIdHEdW12dG8lFS0MbxQ==
|
||||
|
||||
esbuild-linux-mips64le@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.53.tgz#a4d0b6b17cfdeea4e41b0b085a5f73d99311be9f"
|
||||
integrity sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==
|
||||
|
||||
esbuild-linux-mips64le@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.13.tgz#bdf905aae5c0bcaa8f83567fe4c4c1bdc1f14447"
|
||||
integrity sha512-47PgmyYEu+yN5rD/MbwS6DxP2FSGPo4Uxg5LwIdxTiyGC2XKwHhHyW7YYEDlSuXLQXEdTO7mYe8zQ74czP7W8A==
|
||||
|
||||
esbuild-linux-ppc64le@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.53.tgz#8c331822c85465434e086e3e6065863770c38139"
|
||||
integrity sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==
|
||||
|
||||
esbuild-linux-ppc64le@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.13.tgz#2911eae1c90ff58a3bd3259cb557235df25aa3b4"
|
||||
integrity sha512-z6n28h2+PC1Ayle9DjKoBRcx/4cxHoOa2e689e2aDJSaKug3jXcQw7mM+GLg+9ydYoNzj8QxNL8ihOv/OnezhA==
|
||||
|
||||
esbuild-linux-riscv64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.53.tgz#36fd75543401304bea8a2d63bf8ea18aaa508e00"
|
||||
integrity sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==
|
||||
|
||||
esbuild-linux-riscv64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.13.tgz#1837c660be12b1d20d2a29c7189ea703f93e9265"
|
||||
integrity sha512-+Lu4zuuXuQhgLUGyZloWCqTslcCAjMZH1k3Xc9MSEJEpEFdpsSU0sRDXAnk18FKOfEjhu4YMGaykx9xjtpA6ow==
|
||||
|
||||
esbuild-linux-s390x@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.53.tgz#1622677ab6824123f48f75d3afc031cd41936129"
|
||||
integrity sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==
|
||||
|
||||
esbuild-linux-s390x@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.13.tgz#d52880ece229d1bd10b2d936b792914ffb07c7fc"
|
||||
integrity sha512-BMeXRljruf7J0TMxD5CIXS65y7puiZkAh+s4XFV9qy16SxOuMhxhVIXYLnbdfLrsYGFzx7U9mcdpFWkkvy/Uag==
|
||||
|
||||
esbuild-netbsd-64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.53.tgz#e86d0efd0116658be335492ed12e66b26b4baf52"
|
||||
integrity sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==
|
||||
|
||||
esbuild-netbsd-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.13.tgz#de14da46f1d20352b43e15d97a80a8788275e6ed"
|
||||
integrity sha512-EHj9QZOTel581JPj7UO3xYbltFTYnHy+SIqJVq6yd3KkCrsHRbapiPb0Lx3EOOtybBEE9EyqbmfW1NlSDsSzvQ==
|
||||
|
||||
esbuild-openbsd-64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.53.tgz#9bcbbe6f86304872c6e91f64c8eb73fc29c3588b"
|
||||
integrity sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==
|
||||
|
||||
esbuild-openbsd-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.13.tgz#45e8a5fd74d92ad8f732c43582369c7990f5a0ac"
|
||||
integrity sha512-nkuDlIjF/sfUhfx8SKq0+U+Fgx5K9JcPq1mUodnxI0x4kBdCv46rOGWbuJ6eof2n3wdoCLccOoJAbg9ba/bT2w==
|
||||
|
||||
esbuild-sunos-64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.53.tgz#f7a872f7460bfb7b131f7188a95fbce3d1c577e8"
|
||||
integrity sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==
|
||||
|
||||
esbuild-sunos-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.15.13.tgz#f646ac3da7aac521ee0fdbc192750c87da697806"
|
||||
integrity sha512-jVeu2GfxZQ++6lRdY43CS0Tm/r4WuQQ0Pdsrxbw+aOrHQPHV0+LNOLnvbN28M7BSUGnJnHkHm2HozGgNGyeIRw==
|
||||
|
||||
esbuild-windows-32@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.53.tgz#c5e3ca50e2d1439cc2c9fe4defa63bcd474ce709"
|
||||
integrity sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==
|
||||
|
||||
esbuild-windows-32@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.15.13.tgz#fb4fe77c7591418880b3c9b5900adc4c094f2401"
|
||||
integrity sha512-XoF2iBf0wnqo16SDq+aDGi/+QbaLFpkiRarPVssMh9KYbFNCqPLlGAWwDvxEVz+ywX6Si37J2AKm+AXq1kC0JA==
|
||||
|
||||
esbuild-windows-64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.14.53.tgz#ec2ab4a60c5215f092ffe1eab6d01319e88238af"
|
||||
integrity sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==
|
||||
|
||||
esbuild-windows-64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.15.13.tgz#1fca8c654392c0c31bdaaed168becfea80e20660"
|
||||
integrity sha512-Et6htEfGycjDrtqb2ng6nT+baesZPYQIW+HUEHK4D1ncggNrDNk3yoboYQ5KtiVrw/JaDMNttz8rrPubV/fvPQ==
|
||||
|
||||
esbuild-windows-arm64@0.14.53:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.53.tgz#f71d403806bdf9f4a1f9d097db9aec949bd675c8"
|
||||
integrity sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==
|
||||
|
||||
esbuild-windows-arm64@0.15.13:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.13.tgz#4ffd01b6b2888603f1584a2fe96b1f6a6f2b3dd8"
|
||||
integrity sha512-3bv7tqntThQC9SWLRouMDmZnlOukBhOCTlkzNqzGCmrkCJI7io5LLjwJBOVY6kOUlIvdxbooNZwjtBvj+7uuVg==
|
||||
|
||||
esbuild@^0.14.47:
|
||||
version "0.14.53"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.14.53.tgz#20b1007f686e8584f2a01a1bec5a37aac9498ce4"
|
||||
|
@ -1664,33 +1664,33 @@ esbuild@^0.14.47:
|
|||
esbuild-windows-64 "0.14.53"
|
||||
esbuild-windows-arm64 "0.14.53"
|
||||
|
||||
esbuild@^0.15.9:
|
||||
version "0.15.13"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.15.13.tgz#7293480038feb2bafa91d3f6a20edab3ba6c108a"
|
||||
integrity sha512-Cu3SC84oyzzhrK/YyN4iEVy2jZu5t2fz66HEOShHURcjSkOSAVL8C/gfUT+lDJxkVHpg8GZ10DD0rMHRPqMFaQ==
|
||||
esbuild@^0.16.3:
|
||||
version "0.16.13"
|
||||
resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.16.13.tgz#83cd347c28221268bbfa0425db532d7d05f85b48"
|
||||
integrity sha512-oYwFdSEIoKM1oYzyem1osgKJAvg5447XF+05ava21fOtilyb2HeQQh26/74K4WeAk5dZmj/Mx10zUqUnI14jhA==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.15.13"
|
||||
"@esbuild/linux-loong64" "0.15.13"
|
||||
esbuild-android-64 "0.15.13"
|
||||
esbuild-android-arm64 "0.15.13"
|
||||
esbuild-darwin-64 "0.15.13"
|
||||
esbuild-darwin-arm64 "0.15.13"
|
||||
esbuild-freebsd-64 "0.15.13"
|
||||
esbuild-freebsd-arm64 "0.15.13"
|
||||
esbuild-linux-32 "0.15.13"
|
||||
esbuild-linux-64 "0.15.13"
|
||||
esbuild-linux-arm "0.15.13"
|
||||
esbuild-linux-arm64 "0.15.13"
|
||||
esbuild-linux-mips64le "0.15.13"
|
||||
esbuild-linux-ppc64le "0.15.13"
|
||||
esbuild-linux-riscv64 "0.15.13"
|
||||
esbuild-linux-s390x "0.15.13"
|
||||
esbuild-netbsd-64 "0.15.13"
|
||||
esbuild-openbsd-64 "0.15.13"
|
||||
esbuild-sunos-64 "0.15.13"
|
||||
esbuild-windows-32 "0.15.13"
|
||||
esbuild-windows-64 "0.15.13"
|
||||
esbuild-windows-arm64 "0.15.13"
|
||||
"@esbuild/android-arm" "0.16.13"
|
||||
"@esbuild/android-arm64" "0.16.13"
|
||||
"@esbuild/android-x64" "0.16.13"
|
||||
"@esbuild/darwin-arm64" "0.16.13"
|
||||
"@esbuild/darwin-x64" "0.16.13"
|
||||
"@esbuild/freebsd-arm64" "0.16.13"
|
||||
"@esbuild/freebsd-x64" "0.16.13"
|
||||
"@esbuild/linux-arm" "0.16.13"
|
||||
"@esbuild/linux-arm64" "0.16.13"
|
||||
"@esbuild/linux-ia32" "0.16.13"
|
||||
"@esbuild/linux-loong64" "0.16.13"
|
||||
"@esbuild/linux-mips64el" "0.16.13"
|
||||
"@esbuild/linux-ppc64" "0.16.13"
|
||||
"@esbuild/linux-riscv64" "0.16.13"
|
||||
"@esbuild/linux-s390x" "0.16.13"
|
||||
"@esbuild/linux-x64" "0.16.13"
|
||||
"@esbuild/netbsd-x64" "0.16.13"
|
||||
"@esbuild/openbsd-x64" "0.16.13"
|
||||
"@esbuild/sunos-x64" "0.16.13"
|
||||
"@esbuild/win32-arm64" "0.16.13"
|
||||
"@esbuild/win32-ia32" "0.16.13"
|
||||
"@esbuild/win32-x64" "0.16.13"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
|
@ -2553,10 +2553,10 @@ postcss@^8.1.10, postcss@^8.2.9, postcss@^8.4.14:
|
|||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
postcss@^8.4.18:
|
||||
version "8.4.19"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc"
|
||||
integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==
|
||||
postcss@^8.4.20:
|
||||
version "8.4.20"
|
||||
resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56"
|
||||
integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==
|
||||
dependencies:
|
||||
nanoid "^3.3.4"
|
||||
picocolors "^1.0.0"
|
||||
|
@ -2642,10 +2642,10 @@ rollup@^2.75.6:
|
|||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
rollup@^2.79.1:
|
||||
version "2.79.1"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
|
||||
integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
|
||||
rollup@^3.7.0:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.npmmirror.com/rollup/-/rollup-3.9.1.tgz#27501d3d026418765fe379d5620d25954ff2a011"
|
||||
integrity sha512-GswCYHXftN8ZKGVgQhTFUJB/NBXxrRGgO2NCy6E8s1rwEJ4Q9/VttNqcYfEvx4dTo4j58YqdC3OVztPzlKSX8w==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
|
@ -2972,15 +2972,15 @@ vite@^3.0.4:
|
|||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
vite@^3.2.3:
|
||||
version "3.2.3"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-3.2.3.tgz#7a68d9ef73eff7ee6dc0718ad3507adfc86944a7"
|
||||
integrity sha512-h8jl1TZ76eGs3o2dIBSsvXDLb1m/Ec1iej8ZMdz+PsaFUsftZeWe2CZOI3qogEsMNaywc17gu0q6cQDzh/weCQ==
|
||||
vite@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmmirror.com/vite/-/vite-4.0.3.tgz#de27ad3f263a03ae9419cdc8bc07721eadcba8b9"
|
||||
integrity sha512-HvuNv1RdE7deIfQb8mPk51UKjqptO/4RXZ5yXSAvurd5xOckwS/gg8h9Tky3uSbnjYTgUm0hVCet1cyhKd73ZA==
|
||||
dependencies:
|
||||
esbuild "^0.15.9"
|
||||
postcss "^8.4.18"
|
||||
esbuild "^0.16.3"
|
||||
postcss "^8.4.20"
|
||||
resolve "^1.22.1"
|
||||
rollup "^2.79.1"
|
||||
rollup "^3.7.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
|
|
6
go.mod
6
go.mod
|
@ -2,10 +2,11 @@ module github.com/0xJacky/Nginx-UI
|
|||
|
||||
go 1.19
|
||||
|
||||
replace github.com/tufanbarisyildirim/gonginx v0.0.0-20220829083426-44da4d61ef9a => github.com/0xJacky/gonginx v0.0.0-20230104051937-4c3a63627efb
|
||||
|
||||
require (
|
||||
github.com/creack/pty v1.1.18
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/emirpasic/gods v1.18.1
|
||||
github.com/gin-contrib/static v0.0.1
|
||||
github.com/gin-gonic/gin v1.7.4
|
||||
github.com/go-acme/lego/v4 v4.4.0
|
||||
|
@ -16,9 +17,11 @@ require (
|
|||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hpcloud/tail v1.0.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/shirou/gopsutil/v3 v3.21.7
|
||||
github.com/spf13/cast v1.3.1
|
||||
github.com/tufanbarisyildirim/gonginx v0.0.0-20220829083426-44da4d61ef9a
|
||||
github.com/unknwon/com v1.0.1
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||
gopkg.in/ini.v1 v1.62.0
|
||||
|
@ -32,7 +35,6 @@ require (
|
|||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
github.com/golang/protobuf v1.3.4 // indirect
|
||||
github.com/hpcloud/tail v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.2 // indirect
|
||||
github.com/json-iterator/go v1.1.9 // indirect
|
||||
|
|
18
go.sum
18
go.sum
|
@ -23,6 +23,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
|||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/0xJacky/gonginx v0.0.0-20230104051937-4c3a63627efb h1:UzbGgIvP2UXpqlPG0ylT8/y0TIl5tBvAIeI3OAChFHI=
|
||||
github.com/0xJacky/gonginx v0.0.0-20230104051937-4c3a63627efb/go.mod h1:+uQMU+LMBHOQermcm/ICplG+r35Ypb6Up9iYKlvKuTE=
|
||||
github.com/Azure/azure-sdk-for-go v32.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||
github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
|
@ -97,14 +99,13 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
|||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/exoscale/egoscale v0.46.0/go.mod h1:mpEXBpROAa/2i5GC0r33rfxG+TxSEka11g1PIXt9+zc=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
|
@ -172,8 +173,10 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
|
|||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
|
@ -446,6 +449,7 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2
|
|||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
|
@ -502,6 +506,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
|||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -529,6 +534,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d h1:1aflnvSoWWLI2k/dMUAl5lvU1YO4Mb4hz0gh+1rjcxU=
|
||||
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
|
@ -543,6 +549,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -589,6 +596,7 @@ golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
|
@ -641,9 +649,11 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
|
|||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
|
@ -725,6 +735,8 @@ gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9D
|
|||
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||
gorm.io/gorm v1.21.14 h1:NAR9A/3SoyiPVHouW/rlpMUZvuQZ6Z6UYGz+2tosSQo=
|
||||
gorm.io/gorm v1.21.14/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
gotest.tools/v3 v3.2.0 h1:I0DwBVMGAx26dttAj1BtJLAkVGncrkkUXfJLC4Flt/I=
|
||||
gotest.tools/v3 v3.2.0/go.mod h1:Mcr9QNxkg0uMvy/YElmo4SpXgJKWgQvYrT7Kw5RzJ1A=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
@ -1,173 +1,184 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetConfigs(c *gin.Context) {
|
||||
orderBy := c.Query("order_by")
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
dir := c.DefaultQuery("dir", "/")
|
||||
orderBy := c.Query("order_by")
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
dir := c.DefaultQuery("dir", "/")
|
||||
|
||||
mySort := map[string]string{
|
||||
"name": "string",
|
||||
"modify": "time",
|
||||
"is_dir": "bool",
|
||||
}
|
||||
mySort := map[string]string{
|
||||
"name": "string",
|
||||
"modify": "time",
|
||||
"is_dir": "bool",
|
||||
}
|
||||
|
||||
configFiles, err := os.ReadDir(nginx.GetNginxConfPath(dir))
|
||||
configFiles, err := os.ReadDir(nginx.GetNginxConfPath(dir))
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
var configs []gin.H
|
||||
var configs []gin.H
|
||||
|
||||
for i := range configFiles {
|
||||
file := configFiles[i]
|
||||
fileInfo, _ := file.Info()
|
||||
for i := range configFiles {
|
||||
file := configFiles[i]
|
||||
fileInfo, _ := file.Info()
|
||||
|
||||
switch mode := fileInfo.Mode(); {
|
||||
case mode.IsRegular(): // regular file, not a hidden file
|
||||
if "." == file.Name()[0:1] {
|
||||
continue
|
||||
}
|
||||
case mode&os.ModeSymlink != 0: // is a symbol
|
||||
var targetPath string
|
||||
targetPath, err = os.Readlink(nginx.GetNginxConfPath(file.Name()))
|
||||
if err != nil {
|
||||
log.Println("GetConfigs Read Symlink Error", targetPath, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
switch mode := fileInfo.Mode(); {
|
||||
case mode.IsRegular(): // regular file, not a hidden file
|
||||
if "." == file.Name()[0:1] {
|
||||
continue
|
||||
}
|
||||
case mode&os.ModeSymlink != 0: // is a symbol
|
||||
var targetPath string
|
||||
targetPath, err = os.Readlink(nginx.GetNginxConfPath(file.Name()))
|
||||
if err != nil {
|
||||
log.Println("GetConfigs Read Symlink Error", targetPath, err)
|
||||
continue
|
||||
}
|
||||
|
||||
configs = append(configs, gin.H{
|
||||
"name": file.Name(),
|
||||
"size": fileInfo.Size(),
|
||||
"modify": fileInfo.ModTime(),
|
||||
"is_dir": file.IsDir(),
|
||||
})
|
||||
}
|
||||
var targetInfo os.FileInfo
|
||||
targetInfo, err = os.Stat(targetPath)
|
||||
if err != nil {
|
||||
log.Println("GetConfigs Stat Error", targetPath, err)
|
||||
continue
|
||||
}
|
||||
// but target file is not a dir
|
||||
if targetInfo.IsDir() {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
configs = append(configs, gin.H{
|
||||
"name": file.Name(),
|
||||
"size": fileInfo.Size(),
|
||||
"modify": fileInfo.ModTime(),
|
||||
"is_dir": file.IsDir(),
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": configs,
|
||||
})
|
||||
configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": configs,
|
||||
})
|
||||
}
|
||||
|
||||
func GetConfig(c *gin.Context) {
|
||||
name := c.Param("name")
|
||||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
name := c.Param("name")
|
||||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
|
||||
content, err := os.ReadFile(path)
|
||||
content, err := os.ReadFile(path)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"config": string(content),
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"config": string(content),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
type AddConfigJson struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
}
|
||||
|
||||
func AddConfig(c *gin.Context) {
|
||||
var request AddConfigJson
|
||||
err := c.BindJSON(&request)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
var request AddConfigJson
|
||||
err := c.BindJSON(&request)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
name := request.Name
|
||||
content := request.Content
|
||||
name := request.Name
|
||||
content := request.Content
|
||||
|
||||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
|
||||
if _, err = os.Stat(path); err == nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "config exist",
|
||||
})
|
||||
return
|
||||
}
|
||||
if _, err = os.Stat(path); err == nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "config exist",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if content != "" {
|
||||
err = os.WriteFile(path, []byte(content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if content != "" {
|
||||
err = os.WriteFile(path, []byte(content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx.ReloadNginx()
|
||||
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"name": name,
|
||||
"content": content,
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"name": name,
|
||||
"content": content,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
type EditConfigJson struct {
|
||||
Content string `json:"content" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
}
|
||||
|
||||
func EditConfig(c *gin.Context) {
|
||||
name := c.Param("name")
|
||||
var request EditConfigJson
|
||||
err := c.BindJSON(&request)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
content := request.Content
|
||||
name := c.Param("name")
|
||||
var request EditConfigJson
|
||||
err := c.BindJSON(&request)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
content := request.Content
|
||||
|
||||
origContent, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
origContent, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if content != "" && content != string(origContent) {
|
||||
// model.CreateBackup(path)
|
||||
err = os.WriteFile(path, []byte(content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if content != "" && content != string(origContent) {
|
||||
// model.CreateBackup(path)
|
||||
err = os.WriteFile(path, []byte(content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx.ReloadNginx()
|
||||
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
GetConfig(c)
|
||||
GetConfig(c)
|
||||
}
|
||||
|
|
|
@ -1,381 +1,381 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/cert"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/cert"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetDomains(c *gin.Context) {
|
||||
name := c.Query("name")
|
||||
orderBy := c.Query("order_by")
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
name := c.Query("name")
|
||||
orderBy := c.Query("order_by")
|
||||
sort := c.DefaultQuery("sort", "desc")
|
||||
|
||||
mySort := map[string]string{
|
||||
"enabled": "bool",
|
||||
"name": "string",
|
||||
"modify": "time",
|
||||
}
|
||||
mySort := map[string]string{
|
||||
"enabled": "bool",
|
||||
"name": "string",
|
||||
"modify": "time",
|
||||
}
|
||||
|
||||
configFiles, err := os.ReadDir(nginx.GetNginxConfPath("sites-available"))
|
||||
configFiles, err := os.ReadDir(nginx.GetNginxConfPath("sites-available"))
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
enabledConfig, err := os.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
|
||||
enabledConfig, err := os.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
enabledConfigMap := make(map[string]bool)
|
||||
for i := range enabledConfig {
|
||||
enabledConfigMap[enabledConfig[i].Name()] = true
|
||||
}
|
||||
enabledConfigMap := make(map[string]bool)
|
||||
for i := range enabledConfig {
|
||||
enabledConfigMap[enabledConfig[i].Name()] = true
|
||||
}
|
||||
|
||||
var configs []gin.H
|
||||
var configs []gin.H
|
||||
|
||||
for i := range configFiles {
|
||||
file := configFiles[i]
|
||||
fileInfo, _ := file.Info()
|
||||
if !file.IsDir() {
|
||||
if name != "" && !strings.Contains(file.Name(), name) {
|
||||
continue
|
||||
}
|
||||
configs = append(configs, gin.H{
|
||||
"name": file.Name(),
|
||||
"size": fileInfo.Size(),
|
||||
"modify": fileInfo.ModTime(),
|
||||
"enabled": enabledConfigMap[file.Name()],
|
||||
})
|
||||
}
|
||||
}
|
||||
for i := range configFiles {
|
||||
file := configFiles[i]
|
||||
fileInfo, _ := file.Info()
|
||||
if !file.IsDir() {
|
||||
if name != "" && !strings.Contains(file.Name(), name) {
|
||||
continue
|
||||
}
|
||||
configs = append(configs, gin.H{
|
||||
"name": file.Name(),
|
||||
"size": fileInfo.Size(),
|
||||
"modify": fileInfo.ModTime(),
|
||||
"enabled": enabledConfigMap[file.Name()],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": configs,
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": configs,
|
||||
})
|
||||
}
|
||||
|
||||
type CertificateInfo struct {
|
||||
SubjectName string `json:"subject_name"`
|
||||
IssuerName string `json:"issuer_name"`
|
||||
NotAfter time.Time `json:"not_after"`
|
||||
NotBefore time.Time `json:"not_before"`
|
||||
SubjectName string `json:"subject_name"`
|
||||
IssuerName string `json:"issuer_name"`
|
||||
NotAfter time.Time `json:"not_after"`
|
||||
NotBefore time.Time `json:"not_before"`
|
||||
}
|
||||
|
||||
func GetDomain(c *gin.Context) {
|
||||
rewriteName, ok := c.Get("rewriteConfigFileName")
|
||||
rewriteName, ok := c.Get("rewriteConfigFileName")
|
||||
|
||||
name := c.Param("name")
|
||||
name := c.Param("name")
|
||||
|
||||
// for modify filename
|
||||
if ok {
|
||||
name = rewriteName.(string)
|
||||
}
|
||||
// for modify filename
|
||||
if ok {
|
||||
name = rewriteName.(string)
|
||||
}
|
||||
|
||||
path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
|
||||
enabled := true
|
||||
if _, err := os.Stat(filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
|
||||
enabled = false
|
||||
}
|
||||
enabled := true
|
||||
if _, err := os.Stat(filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
config, err := nginx.ParseNgxConfig(path)
|
||||
config, err := nginx.ParseNgxConfig(path)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
certInfoMap := make(map[int]CertificateInfo)
|
||||
var serverName string
|
||||
for serverIdx, server := range config.Servers {
|
||||
for _, directive := range server.Directives {
|
||||
certInfoMap := make(map[int]CertificateInfo)
|
||||
var serverName string
|
||||
for serverIdx, server := range config.Servers {
|
||||
for _, directive := range server.Directives {
|
||||
|
||||
if directive.Directive == "server_name" {
|
||||
serverName = strings.ReplaceAll(directive.Params, " ", "_")
|
||||
continue
|
||||
}
|
||||
if directive.Directive == "server_name" {
|
||||
serverName = strings.ReplaceAll(directive.Params, " ", "_")
|
||||
continue
|
||||
}
|
||||
|
||||
if directive.Directive == "ssl_certificate" {
|
||||
if directive.Directive == "ssl_certificate" {
|
||||
|
||||
pubKey, err := cert.GetCertInfo(directive.Params)
|
||||
pubKey, err := cert.GetCertInfo(directive.Params)
|
||||
|
||||
if err != nil {
|
||||
log.Println("Failed to get certificate information", err)
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("Failed to get certificate information", err)
|
||||
break
|
||||
}
|
||||
|
||||
certInfoMap[serverIdx] = CertificateInfo{
|
||||
SubjectName: pubKey.Subject.CommonName,
|
||||
IssuerName: pubKey.Issuer.CommonName,
|
||||
NotAfter: pubKey.NotAfter,
|
||||
NotBefore: pubKey.NotBefore,
|
||||
}
|
||||
certInfoMap[serverIdx] = CertificateInfo{
|
||||
SubjectName: pubKey.Subject.CommonName,
|
||||
IssuerName: pubKey.Issuer.CommonName,
|
||||
NotAfter: pubKey.NotAfter,
|
||||
NotBefore: pubKey.NotBefore,
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
certModel, _ := model.FirstCert(serverName)
|
||||
certModel, _ := model.FirstCert(serverName)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"enabled": enabled,
|
||||
"name": name,
|
||||
"config": config.BuildConfig(),
|
||||
"tokenized": config,
|
||||
"auto_cert": certModel.AutoCert == model.AutoCertEnabled,
|
||||
"cert_info": certInfoMap,
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"enabled": enabled,
|
||||
"name": name,
|
||||
"config": config.FmtCode(),
|
||||
"tokenized": config,
|
||||
"auto_cert": certModel.AutoCert == model.AutoCertEnabled,
|
||||
"cert_info": certInfoMap,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func EditDomain(c *gin.Context) {
|
||||
name := c.Param("name")
|
||||
name := c.Param("name")
|
||||
|
||||
if name == "" {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "param name is empty",
|
||||
})
|
||||
return
|
||||
}
|
||||
if name == "" {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "param name is empty",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var json struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
var json struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
if !BindAndValid(c, &json) {
|
||||
return
|
||||
}
|
||||
if !BindAndValid(c, &json) {
|
||||
return
|
||||
}
|
||||
|
||||
path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
|
||||
err := os.WriteFile(path, []byte(json.Content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
// rename the config file if needed
|
||||
if name != json.Name {
|
||||
newPath := filepath.Join(nginx.GetNginxConfPath("sites-available"), json.Name)
|
||||
// recreate soft link
|
||||
log.Println(enabledConfigFilePath)
|
||||
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
||||
log.Println(enabledConfigFilePath)
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
enabledConfigFilePath = filepath.Join(nginx.GetNginxConfPath("sites-enabled"), json.Name)
|
||||
err = os.Symlink(newPath, enabledConfigFilePath)
|
||||
err := os.WriteFile(path, []byte(json.Content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
// rename the config file if needed
|
||||
if name != json.Name {
|
||||
newPath := filepath.Join(nginx.GetNginxConfPath("sites-available"), json.Name)
|
||||
// recreate soft link
|
||||
log.Println(enabledConfigFilePath)
|
||||
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
||||
log.Println(enabledConfigFilePath)
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
enabledConfigFilePath = filepath.Join(nginx.GetNginxConfPath("sites-enabled"), json.Name)
|
||||
err = os.Symlink(newPath, enabledConfigFilePath)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
err = os.Rename(path, newPath)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
name = json.Name
|
||||
c.Set("rewriteConfigFileName", name)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
err = os.Rename(path, newPath)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
name = json.Name
|
||||
c.Set("rewriteConfigFileName", name)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
enabledConfigFilePath = filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
||||
// Test nginx configuration
|
||||
err = nginx.TestNginxConf()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
enabledConfigFilePath = filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
||||
// Test nginx configuration
|
||||
err = nginx.TestNginxConf()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx.ReloadNginx()
|
||||
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
GetDomain(c)
|
||||
GetDomain(c)
|
||||
}
|
||||
|
||||
func EnableDomain(c *gin.Context) {
|
||||
configFilePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), c.Param("name"))
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
configFilePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), c.Param("name"))
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
|
||||
_, err := os.Stat(configFilePath)
|
||||
_, err := os.Stat(configFilePath)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) {
|
||||
err = os.Symlink(configFilePath, enabledConfigFilePath)
|
||||
if _, err = os.Stat(enabledConfigFilePath); os.IsNotExist(err) {
|
||||
err = os.Symlink(configFilePath, enabledConfigFilePath)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Test nginx config, if not pass then rollback.
|
||||
err = nginx.TestNginxConf()
|
||||
if err != nil {
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
// Test nginx config, if not pass then rollback.
|
||||
err = nginx.TestNginxConf()
|
||||
if err != nil {
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx.ReloadNginx()
|
||||
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
||||
func DisableDomain(c *gin.Context) {
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
|
||||
_, err := os.Stat(enabledConfigFilePath)
|
||||
_, err := os.Stat(enabledConfigFilePath)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = os.Remove(enabledConfigFilePath)
|
||||
err = os.Remove(enabledConfigFilePath)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// delete auto cert record
|
||||
certModel := model.Cert{Domain: c.Param("name")}
|
||||
err = certModel.Remove()
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
// delete auto cert record
|
||||
certModel := model.Cert{Domain: c.Param("name")}
|
||||
err = certModel.Remove()
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx.ReloadNginx()
|
||||
|
||||
if output != "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
if output != "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": output,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteDomain(c *gin.Context) {
|
||||
var err error
|
||||
name := c.Param("name")
|
||||
availablePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
enabledPath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
var err error
|
||||
name := c.Param("name")
|
||||
availablePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
enabledPath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
|
||||
if _, err = os.Stat(availablePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"message": "site not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
if _, err = os.Stat(availablePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"message": "site not found",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if _, err = os.Stat(enabledPath); err == nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "site is enabled",
|
||||
})
|
||||
return
|
||||
}
|
||||
if _, err = os.Stat(enabledPath); err == nil {
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "site is enabled",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
certModel := model.Cert{Domain: name}
|
||||
_ = certModel.Remove()
|
||||
certModel := model.Cert{Domain: name}
|
||||
_ = certModel.Remove()
|
||||
|
||||
err = os.Remove(availablePath)
|
||||
err = os.Remove(availablePath)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func AddDomainToAutoCert(c *gin.Context) {
|
||||
domain := c.Param("domain")
|
||||
domain = strings.ReplaceAll(domain, " ", "_")
|
||||
certModel, err := model.FirstOrCreateCert(domain)
|
||||
domain := c.Param("domain")
|
||||
domain = strings.ReplaceAll(domain, " ", "_")
|
||||
certModel, err := model.FirstOrCreateCert(domain)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = certModel.Updates(&model.Cert{
|
||||
AutoCert: model.AutoCertEnabled,
|
||||
})
|
||||
err = certModel.Updates(&model.Cert{
|
||||
AutoCert: model.AutoCertEnabled,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, certModel)
|
||||
c.JSON(http.StatusOK, certModel)
|
||||
}
|
||||
|
||||
func RemoveDomainFromAutoCert(c *gin.Context) {
|
||||
domain := c.Param("domain")
|
||||
domain = strings.ReplaceAll(domain, " ", "_")
|
||||
certModel := model.Cert{
|
||||
Domain: domain,
|
||||
}
|
||||
domain := c.Param("domain")
|
||||
domain = strings.ReplaceAll(domain, " ", "_")
|
||||
certModel := model.Cert{
|
||||
Domain: domain,
|
||||
}
|
||||
|
||||
err := certModel.Updates(&model.Cert{
|
||||
AutoCert: model.AutoCertDisabled,
|
||||
})
|
||||
err := certModel.Updates(&model.Cert{
|
||||
AutoCert: model.AutoCertDisabled,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, nil)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, nil)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
nginx2 "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func BuildNginxConfig(c *gin.Context) {
|
||||
var ngxConf nginx2.NgxConfig
|
||||
var ngxConf nginx.NgxConfig
|
||||
if !BindAndValid(c, &ngxConf) {
|
||||
return
|
||||
}
|
||||
|
@ -28,14 +26,7 @@ func TokenizeNginxConfig(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(json.Content))
|
||||
|
||||
ngxConfig, err := nginx2.ParseNgxConfigByScanner("", scanner)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
ngxConfig := nginx.ParseNgxConfigByContent(json.Content)
|
||||
|
||||
c.JSON(http.StatusOK, ngxConfig)
|
||||
|
||||
|
|
|
@ -1,88 +1,90 @@
|
|||
package nginx
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/tufanbarisyildirim/gonginx"
|
||||
"github.com/tufanbarisyildirim/gonginx/parser"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func buildComments(orig string, indent int) (content string) {
|
||||
scanner := bufio.NewScanner(strings.NewReader(orig))
|
||||
for scanner.Scan() {
|
||||
content += strings.Repeat("\t", indent) + "# " + scanner.Text() + "\n"
|
||||
}
|
||||
content = strings.TrimLeft(content, "\n")
|
||||
return
|
||||
scanner := bufio.NewScanner(strings.NewReader(orig))
|
||||
for scanner.Scan() {
|
||||
content += strings.Repeat("\t", indent) + "# " + scanner.Text() + "\n"
|
||||
}
|
||||
content = strings.TrimLeft(content, "\n")
|
||||
return
|
||||
}
|
||||
|
||||
func (c *NgxConfig) BuildConfig() (content string) {
|
||||
|
||||
// Custom
|
||||
if c.Custom != "" {
|
||||
content += fmtCode(c.Custom)
|
||||
content += "\n\n"
|
||||
}
|
||||
// Custom
|
||||
if c.Custom != "" {
|
||||
content += c.Custom
|
||||
content += "\n\n"
|
||||
}
|
||||
|
||||
// Upstreams
|
||||
for _, u := range c.Upstreams {
|
||||
// Upstreams
|
||||
for _, u := range c.Upstreams {
|
||||
|
||||
upstream := ""
|
||||
var comments string
|
||||
for _, directive := range u.Directives {
|
||||
if directive.Comments != "" {
|
||||
comments = buildComments(directive.Comments, 1)
|
||||
}
|
||||
upstream += fmt.Sprintf("%s\t%s;\n", comments, directive.Orig())
|
||||
}
|
||||
comments = buildComments(u.Comments, 1)
|
||||
content += fmt.Sprintf("upstream %s {\n%s%s}\n\n", u.Name, comments, upstream)
|
||||
}
|
||||
upstream := ""
|
||||
var comments string
|
||||
for _, directive := range u.Directives {
|
||||
if directive.Comments != "" {
|
||||
comments = buildComments(directive.Comments, 1)
|
||||
}
|
||||
upstream += fmt.Sprintf("%s\t%s;\n", comments, directive.Orig())
|
||||
}
|
||||
comments = buildComments(u.Comments, 1)
|
||||
content += fmt.Sprintf("upstream %s {\n%s%s}\n\n", u.Name, comments, upstream)
|
||||
}
|
||||
|
||||
// Servers
|
||||
for _, s := range c.Servers {
|
||||
server := ""
|
||||
// Servers
|
||||
for _, s := range c.Servers {
|
||||
server := ""
|
||||
|
||||
// directives
|
||||
for _, directive := range s.Directives {
|
||||
var comments string
|
||||
if directive.Comments != "" {
|
||||
comments = buildComments(directive.Comments, 1)
|
||||
}
|
||||
if directive.Directive == If {
|
||||
server += fmt.Sprintf("%s%s\n", comments, fmtCodeWithIndent(directive.Params, 1))
|
||||
} else if directive.Params != "" {
|
||||
server += fmt.Sprintf("%s\t%s;\n", comments, directive.Orig())
|
||||
}
|
||||
}
|
||||
// directives
|
||||
for _, directive := range s.Directives {
|
||||
var comments string
|
||||
if directive.Comments != "" {
|
||||
comments = buildComments(directive.Comments, 1)
|
||||
}
|
||||
if directive.Params != "" {
|
||||
server += fmt.Sprintf("%s\t%s;\n", comments, directive.Orig())
|
||||
}
|
||||
}
|
||||
|
||||
if len(s.Directives) > 0 {
|
||||
server += "\n"
|
||||
}
|
||||
if len(s.Directives) > 0 {
|
||||
server += "\n"
|
||||
}
|
||||
|
||||
// locations
|
||||
locations := ""
|
||||
for _, location := range s.Locations {
|
||||
locationContent := ""
|
||||
scanner := bufio.NewScanner(strings.NewReader(location.Content))
|
||||
for scanner.Scan() {
|
||||
locationContent += "\t\t" + scanner.Text() + "\n"
|
||||
}
|
||||
var comments string
|
||||
if location.Comments != "" {
|
||||
comments = buildComments(location.Comments, 1)
|
||||
}
|
||||
locations += fmt.Sprintf("%s\tlocation %s {\n%s\t}\n\n", comments, location.Path, locationContent)
|
||||
}
|
||||
// locations
|
||||
locations := ""
|
||||
for _, location := range s.Locations {
|
||||
locationContent := ""
|
||||
scanner := bufio.NewScanner(strings.NewReader(location.Content))
|
||||
for scanner.Scan() {
|
||||
locationContent += "\t\t" + scanner.Text() + "\n"
|
||||
}
|
||||
var comments string
|
||||
if location.Comments != "" {
|
||||
comments = buildComments(location.Comments, 1)
|
||||
}
|
||||
locations += fmt.Sprintf("%s\tlocation %s {\n%s\t}\n\n", comments, location.Path, locationContent)
|
||||
}
|
||||
|
||||
server += locations
|
||||
server += locations
|
||||
|
||||
var comments string
|
||||
if s.Comments != "" {
|
||||
comments = buildComments(s.Comments, 0) + "\n"
|
||||
}
|
||||
var comments string
|
||||
if s.Comments != "" {
|
||||
comments = buildComments(s.Comments, 0) + "\n"
|
||||
}
|
||||
|
||||
content += fmt.Sprintf("%sserver {\n%s}\n\n", comments, server)
|
||||
}
|
||||
|
||||
return
|
||||
content += fmt.Sprintf("%sserver {\n%s}\n\n", comments, server)
|
||||
}
|
||||
p := parser.NewStringParser(content)
|
||||
config := p.Parse()
|
||||
content = gonginx.DumpConfig(config, gonginx.IndentedStyle)
|
||||
return
|
||||
}
|
||||
|
|
36
server/pkg/nginx/conf/test.conf
Normal file
36
server/pkg/nginx/conf/test.conf
Normal file
|
@ -0,0 +1,36 @@
|
|||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name blog.jackyu.cn test.jackyu.cn;
|
||||
|
||||
location /.well-known/acme-challenge {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr:$remote_port;
|
||||
proxy_pass http://127.0.0.1:9180;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name blog.jackyu.cn test.jackyu.cn;
|
||||
ssl_certificate /etc/nginx/ssl/blog.jackyu.cn_test.jackyu.cn/fullchain.cer;
|
||||
ssl_certificate_key /etc/nginx/ssl/blog.jackyu.cn_test.jackyu.cn/private.key;
|
||||
include enable-php-8.conf;
|
||||
|
||||
location /.well-known/acme-challenge {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real_IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $remote_addr:$remote_port;
|
||||
proxy_pass http://127.0.0.1:9180;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,49 +1,10 @@
|
|||
package nginx
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"github.com/emirpasic/gods/stacks/linkedliststack"
|
||||
"strings"
|
||||
"github.com/tufanbarisyildirim/gonginx"
|
||||
)
|
||||
|
||||
func fmtCode(content string) (fmtContent string) {
|
||||
fmtContent = fmtCodeWithIndent(content, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func fmtCodeWithIndent(content string, indent int) (fmtContent string) {
|
||||
/*
|
||||
Format content
|
||||
1. TrimSpace for each line
|
||||
2. use stack to count how many \t should add
|
||||
*/
|
||||
stack := linkedliststack.New()
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(content))
|
||||
|
||||
for scanner.Scan() {
|
||||
text := scanner.Text()
|
||||
text = strings.TrimSpace(text)
|
||||
|
||||
before := stack.Size()
|
||||
|
||||
for _, char := range text {
|
||||
matchParentheses(stack, char)
|
||||
}
|
||||
|
||||
after := stack.Size()
|
||||
|
||||
fmtContent += strings.Repeat("\t", indent)
|
||||
|
||||
if before == after {
|
||||
fmtContent += strings.Repeat("\t", stack.Size()) + text + "\n"
|
||||
} else {
|
||||
fmtContent += text + "\n"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fmtContent = strings.Trim(fmtContent, "\n")
|
||||
|
||||
return
|
||||
func (c *NgxConfig) FmtCode() (fmtContent string) {
|
||||
fmtContent = gonginx.DumpConfig(c.c, gonginx.IndentedStyle)
|
||||
return
|
||||
}
|
||||
|
|
49
server/pkg/nginx/ngx_conf_parse_test.go
Normal file
49
server/pkg/nginx/ngx_conf_parse_test.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package nginx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/tufanbarisyildirim/gonginx"
|
||||
"github.com/tufanbarisyildirim/gonginx/parser"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNgxConfParse(t *testing.T) {
|
||||
p, err := parser.NewParser("conf/nextcloud_ngx.conf")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
n := p.Parse()
|
||||
|
||||
fn(n.Block, 0)
|
||||
|
||||
c, err := ParseNgxConfig("conf/nextcloud_ngx.conf")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(c)
|
||||
c, err = ParseNgxConfig("conf/test.conf")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(c)
|
||||
}
|
||||
|
||||
func fn(block gonginx.IBlock, deep int) {
|
||||
if block == nil {
|
||||
return
|
||||
}
|
||||
for _, v := range block.GetDirectives() {
|
||||
if len(v.GetComment()) > 0 {
|
||||
for _, c := range v.GetComment() {
|
||||
fmt.Println(strings.Repeat("\t", deep), c)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(fmt.Sprintf("%s%s %s", strings.Repeat("\t", deep), v.GetName(), strings.Join(v.GetParameters(), " ")))
|
||||
fn(v.GetBlock(), deep+1)
|
||||
}
|
||||
}
|
|
@ -1,150 +1,158 @@
|
|||
package nginx
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"github.com/emirpasic/gods/stacks/linkedliststack"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"github.com/tufanbarisyildirim/gonginx"
|
||||
"github.com/tufanbarisyildirim/gonginx/parser"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
Server = "server"
|
||||
Location = "location"
|
||||
Upstream = "upstream"
|
||||
CommentStart = "#"
|
||||
Empty = ""
|
||||
If = "if"
|
||||
Server = "server"
|
||||
Location = "location"
|
||||
Upstream = "upstream"
|
||||
)
|
||||
|
||||
func matchParentheses(stack *linkedliststack.Stack, v int32) {
|
||||
if v == '{' {
|
||||
stack.Push(v)
|
||||
} else if v == '}' {
|
||||
// stack is not empty and the top is == '{'
|
||||
if top, ok := stack.Peek(); ok && top == '{' {
|
||||
stack.Pop()
|
||||
} else {
|
||||
// fail
|
||||
stack.Push(v)
|
||||
func (s *NgxServer) parseServer(directive gonginx.IDirective) {
|
||||
if directive.GetBlock() == nil {
|
||||
return
|
||||
}
|
||||
for _, d := range directive.GetBlock().GetDirectives() {
|
||||
switch d.GetName() {
|
||||
case Location:
|
||||
location := &NgxLocation{
|
||||
Path: strings.Join(d.GetParameters(), " "),
|
||||
Comments: buildComment(d.GetComment()),
|
||||
}
|
||||
location.parseLocation(d, 0)
|
||||
s.Locations = append(s.Locations, location)
|
||||
default:
|
||||
dir := &NgxDirective{
|
||||
Directive: d.GetName(),
|
||||
Comments: buildComment(d.GetComment()),
|
||||
}
|
||||
dir.parseDirective(d, 0)
|
||||
s.Directives = append(s.Directives, dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseDirective(scanner *bufio.Scanner) (d NgxDirective) {
|
||||
text := strings.TrimSpace(scanner.Text())
|
||||
// escape empty line or comment line
|
||||
if len(text) < 1 {
|
||||
func (l *NgxLocation) parseLocation(directive gonginx.IDirective, deep int) {
|
||||
if directive.GetBlock() == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if text[0] == '#' {
|
||||
d.Directive = "#"
|
||||
d.Params = strings.TrimLeft(text, "#")
|
||||
return
|
||||
}
|
||||
|
||||
if len(text) > 1 {
|
||||
sep := len(text) - 1
|
||||
for k, v := range text {
|
||||
if unicode.IsSpace(v) {
|
||||
sep = k
|
||||
break
|
||||
for _, location := range directive.GetBlock().GetDirectives() {
|
||||
if len(location.GetComment()) > 0 {
|
||||
for _, c := range location.GetComment() {
|
||||
l.Content += strings.Repeat("\t", deep) + c + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
d.Directive = text[0:sep]
|
||||
d.Params = text[sep:]
|
||||
} else {
|
||||
d.Directive = text
|
||||
return
|
||||
l.Content += strings.Repeat("\t", deep) + location.GetName() + " " + strings.Join(location.GetParameters(), " ") + ";\n"
|
||||
l.parseLocation(location, deep+1)
|
||||
}
|
||||
}
|
||||
|
||||
stack := linkedliststack.New()
|
||||
|
||||
if d.Directive == Server || d.Directive == Upstream || d.Directive == Location || d.Directive == If {
|
||||
// { } in one line
|
||||
// location = /.well-known/carddav { return 301 /remote.php/dav/; }
|
||||
if strings.Contains(d.Params, "{") {
|
||||
for _, v := range d.Params {
|
||||
matchParentheses(stack, v)
|
||||
}
|
||||
|
||||
if stack.Empty() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// location ^~ /.well-known {
|
||||
// location ^~ /.well-known
|
||||
// {
|
||||
// location ^~ /.well-known
|
||||
//
|
||||
// {
|
||||
// { } not in one line
|
||||
for scanner.Scan() {
|
||||
text = strings.TrimSpace(scanner.Text())
|
||||
// escape empty line
|
||||
if text == "" {
|
||||
continue
|
||||
}
|
||||
d.Params += "\n" + scanner.Text()
|
||||
for _, v := range text {
|
||||
matchParentheses(stack, v)
|
||||
if stack.Empty() {
|
||||
break
|
||||
func (d *NgxDirective) parseDirective(directive gonginx.IDirective, deep int) {
|
||||
if directive.GetBlock() != nil {
|
||||
d.Params += directive.GetName() + " "
|
||||
d.Directive = ""
|
||||
}
|
||||
d.Params += strings.Join(directive.GetParameters(), " ")
|
||||
if directive.GetBlock() != nil {
|
||||
d.Params += " {\n"
|
||||
for _, location := range directive.GetBlock().GetDirectives() {
|
||||
if len(location.GetComment()) > 0 {
|
||||
for _, c := range location.GetComment() {
|
||||
d.Params += strings.Repeat("\t", deep) + c + "\n"
|
||||
}
|
||||
}
|
||||
if stack.Empty() {
|
||||
break
|
||||
d.Params += strings.Repeat("\t", deep+1) + location.GetName() + " " +
|
||||
strings.Join(location.GetParameters(), " ") + ";\n"
|
||||
// d.parseDirective(location, deep+1)
|
||||
if location.GetBlock() == nil {
|
||||
continue
|
||||
}
|
||||
for _, v := range location.GetBlock().GetDirectives() {
|
||||
d.parseDirective(v, deep+1)
|
||||
}
|
||||
}
|
||||
d.Params += "}\n"
|
||||
return
|
||||
}
|
||||
d.Params = strings.TrimSpace(d.Params)
|
||||
}
|
||||
|
||||
func (u *NgxUpstream) parseUpstream(directive gonginx.IDirective) {
|
||||
if directive.GetBlock() == nil {
|
||||
return
|
||||
}
|
||||
for _, us := range directive.GetBlock().GetDirectives() {
|
||||
d := &NgxDirective{
|
||||
Directive: us.GetName(),
|
||||
Params: strings.Join(us.GetParameters(), " "),
|
||||
Comments: buildComment(us.GetComment()),
|
||||
}
|
||||
u.Directives = append(u.Directives, d)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *NgxConfig) parseCustom(directive gonginx.IDirective) {
|
||||
if directive.GetBlock() == nil {
|
||||
return
|
||||
}
|
||||
c.Custom += "{\n"
|
||||
for _, v := range directive.GetBlock().GetDirectives() {
|
||||
c.Custom += strings.Join(v.GetComment(), "\n") + "\n" +
|
||||
v.GetName() + " " + strings.Join(v.GetParameters(), " ") + ";\n"
|
||||
}
|
||||
c.Custom += "}\n"
|
||||
}
|
||||
|
||||
func buildComment(c []string) string {
|
||||
return strings.ReplaceAll(strings.Join(c, "\n"), "#", "")
|
||||
}
|
||||
|
||||
func parse(block gonginx.IBlock, ngxConfig *NgxConfig) {
|
||||
if block == nil {
|
||||
return
|
||||
}
|
||||
for _, v := range block.GetDirectives() {
|
||||
comments := buildComment(v.GetComment())
|
||||
switch v.GetName() {
|
||||
case Server:
|
||||
server := NewNgxServer()
|
||||
server.Comments = comments
|
||||
server.parseServer(v)
|
||||
ngxConfig.Servers = append(ngxConfig.Servers, server)
|
||||
case Upstream:
|
||||
upstream := &NgxUpstream{}
|
||||
upstream.Comments = comments
|
||||
upstream.parseUpstream(v)
|
||||
ngxConfig.Upstreams = append(ngxConfig.Upstreams, upstream)
|
||||
default:
|
||||
ngxConfig.Custom += strings.Join(v.GetComment(), "\n") + "\n" +
|
||||
v.GetName() + " " + strings.Join(v.GetParameters(), " ") + "\n"
|
||||
ngxConfig.parseCustom(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ParseNgxConfigByContent(content string) (ngxConfig *NgxConfig) {
|
||||
p := parser.NewStringParser(content)
|
||||
c := p.Parse()
|
||||
ngxConfig = NewNgxConfig("")
|
||||
ngxConfig.c = c
|
||||
parse(c.Block, ngxConfig)
|
||||
return
|
||||
}
|
||||
|
||||
func ParseNgxConfigByScanner(filename string, scanner *bufio.Scanner) (c *NgxConfig, err error) {
|
||||
c = NewNgxConfig(filename)
|
||||
|
||||
for scanner.Scan() {
|
||||
d := parseDirective(scanner)
|
||||
paramsScanner := bufio.NewScanner(strings.NewReader(d.Params))
|
||||
switch d.Directive {
|
||||
case Server:
|
||||
c.parseServer(paramsScanner)
|
||||
case Upstream:
|
||||
c.parseUpstream(paramsScanner)
|
||||
case CommentStart:
|
||||
c.commentQueue.Enqueue(d.Params)
|
||||
case Empty:
|
||||
continue
|
||||
default:
|
||||
c.Custom += d.Orig() + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
if err = scanner.Err(); err != nil {
|
||||
return nil, errors.Wrap(err, "error scanner in ParseNgxConfig")
|
||||
}
|
||||
|
||||
// Attach the rest of the comments to the last server
|
||||
if len(c.Servers) > 0 {
|
||||
c.Servers[len(c.Servers)-1].Comments += c.commentQueue.DequeueAllComments()
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func ParseNgxConfig(filename string) (c *NgxConfig, err error) {
|
||||
file, err := os.Open(filename)
|
||||
func ParseNgxConfig(filename string) (ngxConfig *NgxConfig, err error) {
|
||||
p, err := parser.NewParser(filename)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error open file in ParseNgxConfig")
|
||||
return nil, errors.Wrap(err, "error ParseNgxConfig")
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
return ParseNgxConfigByScanner(filename, scanner)
|
||||
c := p.Parse()
|
||||
ngxConfig = NewNgxConfig(filename)
|
||||
ngxConfig.c = c
|
||||
parse(c.Block, ngxConfig)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,125 +0,0 @@
|
|||
package nginx
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func (c *NgxConfig) parseServer(scanner *bufio.Scanner) {
|
||||
server := NewNgxServer()
|
||||
for scanner.Scan() {
|
||||
d := parseDirective(scanner)
|
||||
switch d.Directive {
|
||||
case Location:
|
||||
server.parseLocation(d.Params)
|
||||
case CommentStart:
|
||||
server.commentQueue.Enqueue(d.Params)
|
||||
default:
|
||||
server.parseDirective(d)
|
||||
}
|
||||
}
|
||||
// Attach the rest of the comments to the last location
|
||||
if len(server.Locations) > 0 {
|
||||
server.Locations[len(server.Locations)-1].Comments += server.commentQueue.DequeueAllComments()
|
||||
}
|
||||
|
||||
// Attach comments which are over the current server
|
||||
server.Comments = c.commentQueue.DequeueAllComments()
|
||||
|
||||
c.Servers = append(c.Servers, server)
|
||||
}
|
||||
|
||||
func (c *NgxConfig) parseUpstream(scanner *bufio.Scanner) {
|
||||
upstream := &NgxUpstream{}
|
||||
for scanner.Scan() {
|
||||
d := NgxDirective{}
|
||||
text := strings.TrimSpace(scanner.Text())
|
||||
// escape empty line or comment line
|
||||
if len(text) < 1 || text[0] == '#' {
|
||||
return
|
||||
}
|
||||
|
||||
sep := len(text) - 1
|
||||
for k, v := range text {
|
||||
if unicode.IsSpace(v) {
|
||||
sep = k
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
d.Directive = text[0:sep]
|
||||
d.Params = strings.Trim(text[sep:], ";")
|
||||
|
||||
if d.Directive == Server {
|
||||
upstream.Directives = append(upstream.Directives, &d)
|
||||
} else if upstream.Name == "" {
|
||||
upstream.Name = d.Directive
|
||||
}
|
||||
}
|
||||
// attach comments which are over the current upstream
|
||||
upstream.Comments = c.commentQueue.DequeueAllComments()
|
||||
|
||||
c.Upstreams = append(c.Upstreams, upstream)
|
||||
}
|
||||
|
||||
func (s *NgxServer) parseDirective(d NgxDirective) {
|
||||
orig := d.Orig()
|
||||
// handle inline comments
|
||||
str, comments, _ := strings.Cut(orig, "#")
|
||||
|
||||
if d.Directive == If {
|
||||
d.Params = "if " + d.Params
|
||||
d.Params = fmtCode(d.Params)
|
||||
s.Directives = append(s.Directives, &d)
|
||||
return
|
||||
}
|
||||
|
||||
regExp := regexp.MustCompile("(\\S+?)\\s+?{?(.+)[;|}]")
|
||||
matchSlice := regExp.FindAllStringSubmatch(str, -1)
|
||||
|
||||
for k, v := range matchSlice {
|
||||
// [[gzip_min_length 256; gzip_min_length 256] [gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth] [gzip on; gzip on] [gzip_vary on; gzip_vary on] [location /x/ {} location /x/ {] [gzip_comp_level 4; gzip_comp_level 4]]
|
||||
if len(v) > 0 {
|
||||
scanner := bufio.NewScanner(strings.NewReader(v[0]))
|
||||
if scanner.Scan() {
|
||||
d = parseDirective(scanner)
|
||||
// inline location
|
||||
if d.Directive == Location {
|
||||
s.parseLocation(d.Orig())
|
||||
} else {
|
||||
|
||||
if k == 0 {
|
||||
d.Comments = s.commentQueue.DequeueAllComments()
|
||||
} else if k == len(matchSlice)-1 {
|
||||
d.Comments = comments
|
||||
}
|
||||
|
||||
// trim right ';'
|
||||
d.TrimParams()
|
||||
// map[directive]=>[]Params
|
||||
s.Directives = append(s.Directives, &d)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *NgxServer) parseLocation(str string) {
|
||||
path, content, _ := strings.Cut(str, "{")
|
||||
path = strings.TrimSpace(path)
|
||||
|
||||
content = strings.TrimSpace(content)
|
||||
content = strings.Trim(content, "}")
|
||||
|
||||
content = fmtCode(content)
|
||||
|
||||
location := &NgxLocation{
|
||||
Path: path,
|
||||
Content: content,
|
||||
}
|
||||
location.Comments = s.commentQueue.DequeueAllComments()
|
||||
s.Locations = append(s.Locations, location)
|
||||
}
|
|
@ -1,27 +1,22 @@
|
|||
package nginx
|
||||
|
||||
import (
|
||||
"github.com/emirpasic/gods/queues/linkedlistqueue"
|
||||
"github.com/tufanbarisyildirim/gonginx"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CommentQueue struct {
|
||||
*linkedlistqueue.Queue
|
||||
}
|
||||
|
||||
type NgxConfig struct {
|
||||
FileName string `json:"file_name"`
|
||||
Upstreams []*NgxUpstream `json:"upstreams"`
|
||||
Servers []*NgxServer `json:"servers"`
|
||||
Custom string `json:"custom"`
|
||||
commentQueue *CommentQueue
|
||||
FileName string `json:"file_name"`
|
||||
Upstreams []*NgxUpstream `json:"upstreams"`
|
||||
Servers []*NgxServer `json:"servers"`
|
||||
Custom string `json:"custom"`
|
||||
c *gonginx.Config
|
||||
}
|
||||
|
||||
type NgxServer struct {
|
||||
Directives []*NgxDirective `json:"directives"`
|
||||
Locations []*NgxLocation `json:"locations"`
|
||||
Comments string `json:"comments"`
|
||||
commentQueue *CommentQueue
|
||||
Directives []*NgxDirective `json:"directives"`
|
||||
Locations []*NgxLocation `json:"locations"`
|
||||
Comments string `json:"comments"`
|
||||
}
|
||||
|
||||
type NgxUpstream struct {
|
||||
|
@ -42,18 +37,6 @@ type NgxLocation struct {
|
|||
Comments string `json:"comments"`
|
||||
}
|
||||
|
||||
func (c *CommentQueue) DequeueAllComments() (comments string) {
|
||||
for !c.Empty() {
|
||||
comment, ok := c.Dequeue()
|
||||
|
||||
if ok {
|
||||
comments += strings.TrimSpace(comment.(string)) + "\n"
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (d *NgxDirective) Orig() string {
|
||||
return d.Directive + " " + d.Params
|
||||
}
|
||||
|
@ -65,16 +48,14 @@ func (d *NgxDirective) TrimParams() {
|
|||
|
||||
func NewNgxServer() *NgxServer {
|
||||
return &NgxServer{
|
||||
Locations: make([]*NgxLocation, 0),
|
||||
Directives: make([]*NgxDirective, 0),
|
||||
commentQueue: &CommentQueue{linkedlistqueue.New()},
|
||||
Locations: make([]*NgxLocation, 0),
|
||||
Directives: make([]*NgxDirective, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func NewNgxConfig(filename string) *NgxConfig {
|
||||
return &NgxConfig{
|
||||
FileName: filename,
|
||||
commentQueue: &CommentQueue{linkedlistqueue.New()},
|
||||
Upstreams: make([]*NgxUpstream, 0),
|
||||
FileName: filename,
|
||||
Upstreams: make([]*NgxUpstream, 0),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNgxConfParse(t *testing.T) {
|
||||
c, err := nginx.ParseNgxConfig("nextcloud_ngx.conf")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(c.FileName)
|
||||
// directive in root
|
||||
fmt.Println("Upstream")
|
||||
for _, u := range c.Upstreams {
|
||||
fmt.Println("upstream name", u.Name)
|
||||
fmt.Printf("comments\n%v", u.Comments)
|
||||
for _, d := range u.Directives {
|
||||
fmt.Println("u.Directives.d", d)
|
||||
}
|
||||
}
|
||||
fmt.Println("==========================")
|
||||
fmt.Println("Servers")
|
||||
for _, s := range c.Servers {
|
||||
fmt.Printf("comments\n%v", s.Comments)
|
||||
for _, d := range s.Directives {
|
||||
fmt.Println(d)
|
||||
}
|
||||
// locations
|
||||
for _, location := range s.Locations {
|
||||
fmt.Printf("comments\n%v", location.Comments)
|
||||
fmt.Println("path", location.Path)
|
||||
fmt.Println("content", location.Content)
|
||||
fmt.Println("==========================")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue