feat(template): add selection box; add scheme and host field for reverse_proxy #608

This commit is contained in:
Jacky 2024-10-14 17:53:02 +08:00
parent 77666f4cc6
commit 91799e64c4
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
20 changed files with 474 additions and 136 deletions

View file

@ -13,7 +13,7 @@ bin = "tmp/main"
# Customize binary.
full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"
# Watch these filename extensions.
include_ext = ["go", "tpl", "tmpl", "html", "toml", "po"]
include_ext = ["go", "tpl", "tmpl", "html", "toml", "po", "conf"]
# Ignore these filename extensions or directories.
exclude_dir = ["assets", "tmp", "vendor", "app/node_modules", "upload", "docs", "resources", ".idea"]
# Watch these directories if you specified.

View file

@ -66,7 +66,6 @@ func GetTemplateConfList(c *gin.Context) {
func GetTemplateBlockList(c *gin.Context) {
configList, err := template.GetTemplateList("block")
if err != nil {
api.ErrHandler(c, err)
return

View file

@ -4,19 +4,18 @@ import type { NgxDirective, NgxLocation, NgxServer } from '@/api/ngx'
export interface Variable {
type?: string
name?: { [key: string]: string }
name?: Record<string, string>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value?: any
mask?: Record<string, Record<string, string>>
}
export interface Template extends NgxServer {
name: string
description: { [key: string]: string }
description: Record<string, string>
author: string
filename: string
variables: {
[key: string]: Variable
}
variables: Record<string, Variable>
custom: string
locations?: NgxLocation[]
directives?: NgxDirective[]

View file

@ -13,6 +13,7 @@ const step = ref(0)
const visible = ref(false)
const data = ref({}) as Ref<AutoCertOptions>
const issuing_cert = ref(false)
const domain = ref('')
provide('issuing_cert', issuing_cert)
function open() {
@ -22,6 +23,7 @@ function open() {
challenge_method: 'dns01',
key_type: '2048',
} as AutoCertOptions
domain.value = ''
}
defineExpose({
@ -32,7 +34,6 @@ const modalVisible = ref(false)
const modalClosable = ref(true)
const refObtainCertLive = ref()
const domain = ref('')
const computedDomain = computed(() => {
return `*.${domain.value}`

View file

@ -173,4 +173,9 @@ function duplicate(index: number) {
.ant-collapse-header {
align-items: center;
}
:deep(.ant-collapse-header-text) {
width: 100%;
overflow: hidden;
}
</style>

View file

@ -119,19 +119,21 @@ provide('ngx_directives', ngx_directives)
>
<p>{{ $gettext('Author') }}: {{ data.author }}</p>
<p>{{ $gettext('Description') }}: {{ trans_description(data) }}</p>
<TemplateForm v-model:data="data.variables" />
<template v-if="data.custom">
<h2>{{ $gettext('Custom') }}</h2>
<TemplateForm v-model="data.variables" />
<div
v-if="data.custom"
class="mb-4"
>
<h3>{{ $gettext('Custom') }}</h3>
<CodeEditor
v-model:content="data.custom"
default-height="150px"
/>
</template>
</div>
<DirectiveEditor
v-if="data.directives"
readonly
/>
<br>
<LocationEditor
v-if="data.locations"
:locations="data.locations"

View file

@ -2,25 +2,8 @@
import TemplateFormItem from '@/views/domain/ngx_conf/config_template/TemplateFormItem.vue'
import type { Variable } from '@/api/template'
const props = defineProps<{
data: {
[key: string]: Variable
}
}>()
const emit = defineEmits<{
'update:data': [data: {
[key: string]: Variable
}]
}>()
const data = computed({
get() {
return props.data
},
set(v) {
emit('update:data', v)
},
const data = defineModel<Record<string, Variable>>({
default: () => {},
})
</script>
@ -29,7 +12,7 @@ const data = computed({
<TemplateFormItem
v-for="(_, k) in data"
:key="k"
v-model:data="data[k]"
v-model="data[k]"
:name="k.toString()"
/>
</AForm>

View file

@ -4,35 +4,32 @@ import _ from 'lodash'
import { useSettingsStore } from '@/pinia'
import type { Variable } from '@/api/template'
const props = defineProps<{
data: Variable
name: string
}>()
const emit = defineEmits<{
'update:data': [data: Variable]
}>()
const data = computed({
get() {
return props.data
},
set(v) {
emit('update:data', v)
},
const data = defineModel<Variable>({
default: () => {},
})
const { language } = storeToRefs(useSettingsStore())
const trans_name = computed(() => {
return props.data?.name?.[language.value] ?? props.data?.name?.en ?? ''
return data.value?.name?.[language.value] ?? data.value?.name?.en ?? ''
})
const build_template = inject('build_template') as () => void
const value = computed(() => props.data.value)
const value = computed(() => data.value.value)
watch(value, _.throttle(build_template, 500))
const selectOptions = computed(() => {
return Object.keys(data.value?.mask || {}).map(k => {
const label = data.value.mask?.[k]?.[language.value] ?? data.value.mask?.[k]?.en ?? ''
return {
label,
value: k,
}
})
})
</script>
<template>
@ -41,6 +38,11 @@ watch(value, _.throttle(build_template, 500))
v-if="data.type === 'string'"
v-model:value="data.value"
/>
<ASelect
v-else-if="data.type === 'select'"
v-model:value="data.value"
:options="selectOptions"
/>
<ASwitch
v-else-if="data.type === 'boolean'"
v-model:checked="data.value"

View file

@ -31,6 +31,7 @@ export const zhTWConfig: LocaleSpecificConfig<DefaultTheme.Config> = {
items: [
{text: '構建', link: '/zh_TW/guide/build'},
{text: '專案結構', link: '/zh_TW/guide/project-structure'},
{text: '配置模板', link: '/zh_TW/guide/nginx-ui-template'},
{text: '貢獻程式碼', link: '/zh_TW/guide/contributing'}
]
},

View file

@ -13,31 +13,71 @@ Please note, you need to recompile the backend after modifying or adding new con
Nginx UI Template file consists of two parts: the file header and the actual Nginx configuration.
Below is a configuration template for hotlink protection, which we will use as a basis to introduce the file format and related syntax of Nginx UI Template.
Below is a configuration template for reverse proxy, which we will use as a basis to introduce the file format and related syntax of Nginx UI Template.
```nginx configuration
# Nginx UI Template Start
name = "Hotlink Protection"
name = "Reverse Proxy"
author = "@0xJacky"
description = { en = "Hotlink Protection Config Template", zh_CN = "防盗链配置模板"}
description = { en = "Reverse Proxy Config", zh_CN = "反向代理配置"}
[variables.NoneReferer]
[variables.enableWebSocket]
type = "boolean"
name = { en = "Allow Referer is None", zh_CN = "允许空 Referer"}
value = false
name = { en = "Enable WebSocket", zh_CN = "启用 WebSocket"}
value = true
[variables.AllowReferers]
[variables.clientMaxBodySize]
type = "string"
name = { en = "Allow Referers", zh_CN = "允许的 Referers"}
value = ""
name = { en = "Client Max Body Size", zh_CN = "客户端最大请求内容大小"}
value = "1000m"
[variables.scheme]
type = "select"
name = { en = "Scheme", zh_CN = "协议"}
value = "http"
mask = { http = { en = "HTTP" }, https = { en = "HTTPS" } }
[variables.host]
type = "string"
name = { en = "Host", zh_CN = "主机"}
value = "127.0.0.1"
[variables.port]
type = "string"
name = { en = "Port", zh_CN = "端口"}
value = 9000
# Nginx UI Template End
location ~ .*\.(jpg|png|js|css)$ {
valid_referers {{- if .NoneReferer}} none {{- end}} blocked server_names {{if .AllowReferers}}{{.AllowReferers}}{{- end}};
if ($invalid_referer) {
return 403;
}
# Nginx UI Custom Start
{{- if .enableWebSocket }}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
{{- end }}
# Nginx UI Custom End
if ($host != $server_name) {
return 404;
}
location / {
{{ if .enableWebSocket }}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{{ end }}
client_max_body_size {{ .clientMaxBodySize }};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass {{ .scheme }}://{{ .host }}:{{ .port }}/;
}
```
## File Header
@ -51,27 +91,44 @@ The file header includes the following fields:
| `name` | Name of the configuration | string | Yes |
| `author` | Author | string | Yes |
| `description` | Desciption, uses a toml dictionary for multi-language support | toml dictionary | Yes |
| `variables.VariableName.type` | Variable type, currently supports `boolean` and `string` | string | No |
| `variables.VariableName.name` | Variable display name, is a toml dictionary to support multi-language | toml dictionary | No |
| `variables.VariableName.type` | Variable type, currently supports `boolean`, `string` and `select` | string | Yes |
| `variables.VariableName.name` | Variable display name, is a toml dictionary to support multi-language | toml dictionary | Yes |
| `variables.VariableName.value` | Default value of the variable | boolean/string (according to type definition) | No |
| `variables.VariableName.mask` | The options of select | toml dictionary | No |
Example:
```toml
# Nginx UI Template Start
name = "Hotlink Protection"
name = "Reverse Proxy"
author = "@0xJacky"
description = { en = "Hotlink Protection Config Template", zh_CN = "防盗链配置模板"}
description = { en = "Reverse Proxy Config", zh_CN = "反向代理配置"}
[variables.NoneReferer]
[variables.enableWebSocket]
type = "boolean"
name = { en = "Allow Referer is None", zh_CN = "允许空 Referer"}
value = false
name = { en = "Enable WebSocket", zh_CN = "启用 WebSocket"}
value = true
[variables.AllowReferers]
[variables.clientMaxBodySize]
type = "string"
name = { en = "Allow Referers", zh_CN = "允许的 Referers"}
value = ""
name = { en = "Client Max Body Size", zh_CN = "客户端最大请求内容大小"}
value = "1000m"
[variables.scheme]
type = "select"
name = { en = "Scheme", zh_CN = "协议"}
value = "http"
mask = { http = { en = "HTTP" }, https = { en = "HTTPS" } }
[variables.host]
type = "string"
name = { en = "Host", zh_CN = "主机"}
value = "127.0.0.1"
[variables.port]
type = "string"
name = { en = "Port", zh_CN = "端口"}
value = 9000
# Nginx UI Template End
```
@ -83,29 +140,45 @@ When you click the "View" button, a dialog will appear, as shown below.
<img src="/assets/nginx-ui-template/en/config-ui.png" width="350px" title="Config Modal" />
The input boxes and switches in the interface correspond to the variable types `boolean` and `string`.
The following table shows the relationship between the variable type and the UI element:
| Variable Type | UI Element |
|:-------------:|:----------:|
| `boolean` | switcher |
| `string` | input |
| `select` | select |
## Nginx Configuration
The Nginx configuration should be provided after the file header. This part will be parsed using the Go `text/template` library. This library provides powerful template generation capabilities, including conditional judgment, looping, and complex text processing, etc.
For more information, please check [Go Documentation](https://pkg.go.dev/text/template).
The variables defined in the header can be used in this part, such as `.NoneReferer` and `.AllowReferers`.
The variables defined in the header can be used in this part, such as `.scheme`, `.host` and `.port`.
Please note that you need to define the variables in the header in advance before using them in this part.
Here is an example:
```nginx configuration
location ~ .*\.(jpg|png|js|css)$ {
valid_referers {{- if .NoneReferer}} none {{- end}} blocked server_names {{if .AllowReferers}}{{.AllowReferers}}{{- end}};
if ($invalid_referer) {
return 403;
location / {
{{ if .enableWebSocket }}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{{ end }}
client_max_body_size {{ .clientMaxBodySize }};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_pass {{ .scheme }}://{{ .host }}:{{ .port }}/;
}
}
```
When users input variable values in the app input boxes, the system will automatically generate new configuration content, as shown below:
<img src="/assets/nginx-ui-template/en/config-ui-after-input.png" width="350px" title="Config Modal" />
When users change the form, the system will automatically generate new configuration content based on the template and the input of user.
In addition to the variables defined in the template header, we also provide macro-defined variables, as shown in the table below:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 192 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 192 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 189 KiB

Before After
Before After

View file

@ -12,31 +12,71 @@ Nginx UI Template 提供了一种开箱即用的配置模板机制。在 NgxConf
Nginx UI Template 文件由两部分组成:文件头部以及具体的 Nginx 配置。
以下是一个关于防盗链的配置模板,我们将以这个模板为基础为您介绍 Nginx UI Template 的文件格式及相关语法。
以下是一个关于反向代理的配置模板,我们将以这个模板为基础为您介绍 Nginx UI Template 的文件格式及相关语法。
```nginx configuration
# Nginx UI Template Start
name = "Hotlink Protection"
name = "Reverse Proxy"
author = "@0xJacky"
description = { en = "Hotlink Protection Config Template", zh_CN = "防盗链配置模板"}
description = { en = "Reverse Proxy Config", zh_CN = "反向代理配置"}
[variables.NoneReferer]
[variables.enableWebSocket]
type = "boolean"
name = { en = "Allow Referer is None", zh_CN = "允许空 Referer"}
value = false
name = { en = "Enable WebSocket", zh_CN = "启用 WebSocket"}
value = true
[variables.AllowReferers]
[variables.clientMaxBodySize]
type = "string"
name = { en = "Allow Referers", zh_CN = "允许的 Referers"}
value = ""
name = { en = "Client Max Body Size", zh_CN = "客户端最大请求内容大小"}
value = "1000m"
[variables.scheme]
type = "select"
name = { en = "Scheme", zh_CN = "协议"}
value = "http"
mask = { http = { en = "HTTP" }, https = { en = "HTTPS" } }
[variables.host]
type = "string"
name = { en = "Host", zh_CN = "主机"}
value = "127.0.0.1"
[variables.port]
type = "string"
name = { en = "Port", zh_CN = "端口"}
value = 9000
# Nginx UI Template End
location ~ .*\.(jpg|png|js|css)$ {
valid_referers {{- if .NoneReferer}} none {{- end}} blocked server_names {{if .AllowReferers}}{{.AllowReferers}}{{- end}};
if ($invalid_referer) {
return 403;
}
# Nginx UI Custom Start
{{- if .enableWebSocket }}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
{{- end }}
# Nginx UI Custom End
if ($host != $server_name) {
return 404;
}
location / {
{{ if .enableWebSocket }}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{{ end }}
client_max_body_size {{ .clientMaxBodySize }};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass {{ .scheme }}://{{ .host }}:{{ .port }}/;
}
```
## 文件头部
@ -46,31 +86,48 @@ location ~ .*\.(jpg|png|js|css)$ {
文件头部包含以下字段:
| 字段 | 描述 | 类型 | 必要 |
|:----------------------:|:------------------------------:|:---------------------------:|:--:|
|:----------------------:|:----------------------------------------:|:---------------------------:|:--:|
| `name` | 配置的名称 | string | 是 |
| `author` | 作者 | string | 是 |
| `description` | 描述,使用 toml 格式的字典来实现多语言描述 | toml 字典 | 是 |
| `variables.变量名称.type` | 变量类型,目前支持 `boolean``string` | string (boolean/string) | 否 |
| `variables.变量名称.name` | 变量显示的名称,是一个 toml 格式的字典,用于支持多语言 | toml 字典 | 否 |
| `variables.变量名称.type` | 变量类型,目前支持 `boolean`, `string``select` | string | 是 |
| `variables.变量名称.name` | 变量显示的名称,是一个 toml 格式的字典,用于支持多语言 | toml 字典 | 是 |
| `variables.变量名称.value` | 变量的默认值 | boolean/string (根据 type 定义) | 否 |
| `variables.变量名称.mask` | 选择框的选项 | toml 字典 | 否 |
示例如下:
```toml
# Nginx UI Template Start
name = "Hotlink Protection"
name = "Reverse Proxy"
author = "@0xJacky"
description = { en = "Hotlink Protection Config Template", zh_CN = "防盗链配置模板"}
description = { en = "Reverse Proxy Config", zh_CN = "反向代理配置"}
[variables.NoneReferer]
[variables.enableWebSocket]
type = "boolean"
name = { en = "Allow Referer is None", zh_CN = "允许空 Referer"}
value = false
name = { en = "Enable WebSocket", zh_CN = "启用 WebSocket"}
value = true
[variables.AllowReferers]
[variables.clientMaxBodySize]
type = "string"
name = { en = "Allow Referers", zh_CN = "允许的 Referers"}
value = ""
name = { en = "Client Max Body Size", zh_CN = "客户端最大请求内容大小"}
value = "1000m"
[variables.scheme]
type = "select"
name = { en = "Scheme", zh_CN = "协议"}
value = "http"
mask = { http = { en = "HTTP" }, https = { en = "HTTPS" } }
[variables.host]
type = "string"
name = { en = "Host", zh_CN = "主机"}
value = "127.0.0.1"
[variables.port]
type = "string"
name = { en = "Port", zh_CN = "端口"}
value = 9000
# Nginx UI Template End
```
@ -82,7 +139,14 @@ value = ""
<img src="/assets/nginx-ui-template/zh_CN/config-ui.png" width="350px" title="配置 Modal" />
界面中的输入框和开关对应着变量的类型 `boolean``string`
下表展示了变量类型与用户界面元素的关系:
| 类型 | 用户界面元素 |
|:---------:|:------:|
| `boolean` | 开关 |
| `string` | 输入框 |
| `select` | 选择框 |
## Nginx 配置
Nginx 配置应该在文件头部之后提供,这部分将使用 Go 的 `text/template` 库进行解析。这个库提供了强大的模板生成能力,包括条件判断、循环以及复杂的文本处理等。
@ -93,16 +157,27 @@ Nginx 配置应该在文件头部之后提供,这部分将使用 Go 的 `text/
示例如下:
```nginx configuration
location ~ .*\.(jpg|png|js|css)$ {
valid_referers {{- if .NoneReferer}} none {{- end}} blocked server_names {{if .AllowReferers}}{{.AllowReferers}}{{- end}};
if ($invalid_referer) {
return 403;
location / {
{{ if .enableWebSocket }}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{{ end }}
client_max_body_size {{ .clientMaxBodySize }};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_pass {{ .scheme }}://{{ .host }}:{{ .port }}/;
}
}
```
当用户在前端的输入框中输入变量的值后,系统将会自动生成新的配置内容,效果如下:
<img src="/assets/nginx-ui-template/zh_CN/config-ui-after-input.png" width="350px" title="配置 Modal" />
当用户修改前端的表单后,系统将会根据用户的输入和配置模板自动生成新的配置内容。
除了模板头部定义的变量,我们还提供了宏定义的变量,如下表所示:

View file

@ -0,0 +1,189 @@
# 配置模板
Nginx UI Template 提供了一種開箱即用的配置模板機制。在 NgxConfigEditor 中,我們設計了一個可視化界面,使使用者能夠方便地將模板中的配置插入到當前的配置文件中。
在本指南中,我們將介紹這種配置模板的文件格式和語法規則。
配置模板文件存儲在 `template/block` 目錄中,我們歡迎並期待您通過提交 [PR](https://github.com/0xJacky/nginx-ui/pulls) 的形式分享您編寫的配置模板。
::: tip
請注意,每次修改或新增配置文件後,需要重新編譯後端以生效。
:::
## 文件格式
Nginx UI Template 文件由兩部分組成:文件頭部以及具體的 Nginx 配置。
以下是一個關於反向代理的配置模板,我們將以此模板為基礎向您介紹 Nginx UI Template 的文件格式及相關語法。
```nginx configuration
# Nginx UI Template Start
name = "Reverse Proxy"
author = "@0xJacky"
description = { en = "Reverse Proxy Config", zh_CN = "反向代理配置"}
[variables.enableWebSocket]
type = "boolean"
name = { en = "Enable WebSocket", zh_CN = "啟用 WebSocket"}
value = true
[variables.clientMaxBodySize]
type = "string"
name = { en = "Client Max Body Size", zh_CN = "客戶端最大請求內容大小"}
value = "1000m"
[variables.scheme]
type = "select"
name = { en = "Scheme", zh_CN = "協議"}
value = "http"
mask = { http = { en = "HTTP" }, https = { en = "HTTPS" } }
[variables.host]
type = "string"
name = { en = "Host", zh_CN = "主機"}
value = "127.0.0.1"
[variables.port]
type = "string"
name = { en = "Port", zh_CN = "端口"}
value = 9000
# Nginx UI Template End
# Nginx UI Custom Start
{{- if .enableWebSocket }}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
{{- end }}
# Nginx UI Custom End
if ($host != $server_name) {
return 404;
}
location / {
{{ if .enableWebSocket }}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{{ end }}
client_max_body_size {{ .clientMaxBodySize }};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass {{ .scheme }}://{{ .host }}:{{ .port }}/;
}
```
## 文件頭部
文件頭部應包含在 `# Nginx UI Template Start``# Nginx UI Template End` 之間,並遵循 toml 語法。
文件頭部包含以下欄位:
| 欄位 | 描述 | 類型 | 必要 |
|:----------------------:|:----------------------------------------:|:---------------------------:|:--:|
| `name` | 配置的名稱 | string | 是 |
| `author` | 作者 | string | 是 |
| `description` | 描述,使用 toml 格式的字典來實現多語言描述 | toml 字典 | 是 |
| `variables.變量名稱.type` | 變量類型,目前支持 `boolean`, `string``select` | string | 是 |
| `variables.變量名稱.name` | 變量顯示的名稱,是一個 toml 格式的字典,用於支持多語言 | toml 字典 | 是 |
| `variables.變量名稱.value` | 變量的默認值 | boolean/string (根據 type 定義) | 否 |
| `variables.變量名稱.mask` | 選擇框的選項 | toml 字典 | 否 |
示例如下:
```toml
# Nginx UI Template Start
name = "Reverse Proxy"
author = "@0xJacky"
description = { en = "Reverse Proxy Config", zh_CN = "反向代理配置"}
[variables.enableWebSocket]
type = "boolean"
name = { en = "Enable WebSocket", zh_CN = "啟用 WebSocket"}
value = true
[variables.clientMaxBodySize]
type = "string"
name = { en = "Client Max Body Size", zh_CN = "客戶端最大請求內容大小"}
value = "1000m"
[variables.scheme]
type = "select"
name = { en = "Scheme", zh_CN = "協議"}
value = "http"
mask = { http = { en = "HTTP" }, https = { en = "HTTPS" } }
[variables.host]
type = "string"
name = { en = "Host", zh_CN = "主機"}
value = "127.0.0.1"
[variables.port]
type = "string"
name = { en = "Port", zh_CN = "端口"}
value = 9000
# Nginx UI Template End
```
其中,名稱、作者及描述將會以摘要的形式在配置列表中顯示。
![配置列表](/assets/nginx-ui-template/zh_TW/config-template-list.png)
當您點擊「查看」按鈕,界面會顯示一個對話框,如下圖所示。
<img src="/assets/nginx-ui-template/zh_TW/config-ui.png" width="350px" title="配置 Modal" />
下表展示了變量類型與使用者界面元素的關係:
| 類型 | 使用者界面元素 |
|:---------:|:------:|
| `boolean` | 開關 |
| `string` | 輸入框 |
| `select` | 選擇框 |
## Nginx 配置
Nginx 配置應該在文件頭部之後提供,這部分將使用 Go 的 `text/template` 庫進行解析。這個庫提供了強大的模板生成能力,包括條件判斷、循環以及複雜的文本處理等。
具體語法可以參考 [Go 文件](https://pkg.go.dev/text/template)。
在頭部中定義的變量可以在這部分中使用,如 `.NoneReferer``.AllowReferers`。請注意,需要預先在頭部定義變量,才能在這部分中使用。
示例如下:
```nginx configuration
location / {
{{ if .enableWebSocket }}
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
{{ end }}
client_max_body_size {{ .clientMaxBodySize }};
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_pass {{ .scheme }}://{{ .host }}:{{ .port }}/;
}
```
當使用者修改前端的表單後,系統將會根據使用者的輸入和配置模板自動生成新的配置內容。
除了模板頭部定義的變量,我們還提供了宏定義的變量,如下表所示:
| 變量名 | 描述 |
|:----------:|:-----------------------:|
| HTTPPORT | Nginx UI 監聽的端口 |
| HTTP01PORT | 用於 HTTP01 Challenge 的端口 |
上述變量可以直接在配置部分使用,無需在頭部定義。

View file

@ -19,9 +19,10 @@ import (
)
type Variable struct {
Type string `json:"type"`
Type string `json:"type"` // string, bool, select
Name map[string]string `json:"name"`
Value interface{} `json:"value"`
Mask map[string]map[string]string `json:"mask,omitempty"`
}
type ConfigInfoItem struct {
@ -48,22 +49,22 @@ func GetTemplateInfo(path, name string) (configListItem ConfigInfoItem) {
}(file)
r := bufio.NewReader(file)
bytes, _, err := r.ReadLine()
lineBytes, _, err := r.ReadLine()
if err == io.EOF {
return
}
line := strings.TrimSpace(string(bytes))
line := strings.TrimSpace(string(lineBytes))
if line != "# Nginx UI Template Start" {
return
}
var content string
for {
bytes, _, err = r.ReadLine()
lineBytes, _, err = r.ReadLine()
if err == io.EOF {
break
}
line = strings.TrimSpace(string(bytes))
line = strings.TrimSpace(string(lineBytes))
if line == "# Nginx UI Template End" {
break
}
@ -123,7 +124,6 @@ func ParseTemplate(path, name string, bindData map[string]Variable) (c ConfigDet
}
t, err := template.New(name).Parse(custom)
if err != nil {
err = errors.Wrap(err, "error parse template.custom")
return
@ -147,7 +147,6 @@ func ParseTemplate(path, name string, bindData map[string]Variable) (c ConfigDet
content = templatePart[1]
t, err = template.New(name).Parse(content)
if err != nil {
err = errors.Wrap(err, "error parse template")
return

View file

@ -13,13 +13,23 @@ type = "string"
name = { en = "Client Max Body Size", zh_CN = "客户端最大请求内容大小"}
value = "1000m"
[variables.scheme]
type = "select"
name = { en = "Scheme", zh_CN = "协议"}
value = "http"
mask = { http = { en = "HTTP" }, https = { en = "HTTPS" } }
[variables.host]
type = "string"
name = { en = "Host", zh_CN = "主机"}
value = "127.0.0.1"
[variables.port]
type = "string"
name = { en = "Port", zh_CN = "端口"}
value = 9000
# Nginx UI Template End
# Nginx UI Custom Start
{{- if .enableWebSocket }}
map $http_upgrade $connection_upgrade {
@ -67,5 +77,5 @@ location / {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_pass http://127.0.0.1:{{ .port }}/;
proxy_pass {{ .scheme }}://{{ .host }}:{{ .port }}/;
}