Skip to content

Commit 2d30e1e

Browse files
committed
feat: check nginx config syntax before save
1 parent 1aa8334 commit 2d30e1e

File tree

4 files changed

+436
-377
lines changed

4 files changed

+436
-377
lines changed

frontend/src/views/domain/DomainEdit.vue

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
44
55
import NgxConfigEditor from '@/views/domain/ngx_conf/NgxConfigEditor'
66
import {useGettext} from 'vue3-gettext'
7-
import {reactive, ref, watch} from 'vue'
7+
import {computed, reactive, ref, watch} from 'vue'
88
import {useRoute, useRouter} from 'vue-router'
99
import domain from '@/api/domain'
1010
import ngx from '@/api/ngx'
1111
import {message} from 'ant-design-vue'
12+
import config from '@/api/config'
1213
1314
1415
const {$gettext, interpolate} = useGettext()
@@ -35,17 +36,30 @@ const auto_cert = ref(false)
3536
const enabled = ref(false)
3637
const configText = ref('')
3738
const ok = ref(false)
38-
const advance_mode = ref(false)
39+
const advance_mode_ref = ref(false)
3940
const saving = ref(false)
4041
const filename = ref('')
42+
const parse_error_status = ref(false)
43+
const parse_error_message = ref('')
4144
4245
init()
4346
47+
const advance_mode = computed({
48+
get() {
49+
return advance_mode_ref.value || parse_error_status.value
50+
},
51+
set(v) {
52+
advance_mode_ref.value = v
53+
}
54+
})
55+
4456
function handle_response(r: any) {
4557
4658
Object.keys(cert_info_map).forEach(v => {
4759
delete cert_info_map[v]
4860
})
61+
parse_error_status.value = false
62+
parse_error_message.value = ''
4963
filename.value = r.name
5064
configText.value = r.config
5165
enabled.value = r.enabled
@@ -58,10 +72,22 @@ function init() {
5872
if (name.value) {
5973
domain.get(name.value).then((r: any) => {
6074
handle_response(r)
61-
}).catch(r => {
62-
message.error(r.message ?? $gettext('Server error'))
75+
}).catch(handle_parse_error)
76+
}
77+
}
78+
79+
function handle_parse_error(r: any) {
80+
if (r?.error === 'nginx_config_syntax_error') {
81+
parse_error_status.value = true
82+
parse_error_message.value = r.message
83+
config.get('sites-available/' + name.value).then(r => {
84+
configText.value = r.config
6385
})
86+
} else {
87+
message.error(r.message ?? $gettext('Server error'))
6488
}
89+
90+
throw r
6591
}
6692
6793
function on_mode_change(advance_mode: boolean) {
@@ -70,35 +96,34 @@ function on_mode_change(advance_mode: boolean) {
7096
} else {
7197
return ngx.tokenize_config(configText.value).then((r: any) => {
7298
Object.assign(ngx_config, r)
73-
}).catch((e: any) => {
74-
message.error(e?.message ?? $gettext('Server error'))
75-
})
99+
}).catch(handle_parse_error)
76100
}
77101
}
78102
79103
function build_config() {
80104
return ngx.build_config(ngx_config).then((r: any) => {
81105
configText.value = r.content
82-
}).catch((e: any) => {
83-
message.error(e?.message ?? $gettext('Server error'))
84106
})
85107
}
86108
87109
const save = async () => {
88110
saving.value = true
89111
90112
if (!advance_mode.value) {
91-
await build_config()
113+
try {
114+
await build_config()
115+
} catch (e) {
116+
saving.value = false
117+
message.error($gettext('Failed to save, syntax error(s) was detected in the configuration.'))
118+
return
119+
}
92120
}
93121
94-
domain.save(name.value, {name: filename.value, content: configText.value}).then(r => {
122+
domain.save(name.value, {name: filename.value || name.value, content: configText.value}).then(r => {
95123
handle_response(r)
96124
router.push('/domain/' + filename.value)
97125
message.success($gettext('Saved successfully'))
98-
99-
}).catch((e: any) => {
100-
message.error(e?.message ?? $gettext('Server error'))
101-
}).finally(() => {
126+
}).catch(handle_parse_error).finally(() => {
102127
saving.value = false
103128
})
104129
@@ -145,7 +170,8 @@ function on_change_enabled(checked: boolean) {
145170
<template #extra>
146171
<div class="mode-switch">
147172
<div class="switch">
148-
<a-switch size="small" v-model:checked="advance_mode" @change="on_mode_change"/>
173+
<a-switch size="small" :disabled="parse_error_status"
174+
v-model:checked="advance_mode" @change="on_mode_change"/>
149175
</div>
150176
<template v-if="advance_mode">
151177
<div>{{ $gettext('Advance Mode') }}</div>
@@ -158,7 +184,16 @@ function on_change_enabled(checked: boolean) {
158184

159185
<transition name="slide-fade">
160186
<div v-if="advance_mode" key="advance">
161-
<code-editor v-model:content="configText"/>
187+
<div class="parse-error-alert-wrapper" v-if="parse_error_status">
188+
<a-alert :message="$gettext('Nginx Configuration Parse Error')"
189+
:description="parse_error_message"
190+
type="error"
191+
show-icon
192+
/>
193+
</div>
194+
<div>
195+
<code-editor v-model:content="configText"/>
196+
</div>
162197
</div>
163198

164199
<div class="domain-edit-container" key="basic" v-else>
@@ -214,6 +249,10 @@ function on_change_enabled(checked: boolean) {
214249
}
215250
}
216251
252+
.parse-error-alert-wrapper {
253+
margin-bottom: 20px;
254+
}
255+
217256
.domain-edit-container {
218257
max-width: 800px;
219258
margin: 0 auto;

0 commit comments

Comments
 (0)