mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-06 23:56:37 +08:00
[功能] 支持为 HTTPS 启用多个证书,更新相关逻辑和测试
This commit is contained in:
@@ -300,9 +300,6 @@ function PublishPreviewCard({
|
||||
<p className="text-sm font-semibold text-[var(--foreground-primary)]">
|
||||
Pending Main Config
|
||||
</p>
|
||||
<p className="text-xs text-[var(--foreground-secondary)]">
|
||||
{`Checksum: ${preview.checksum}`}
|
||||
</p>
|
||||
</div>
|
||||
<CodeBlock className="max-h-[32rem] whitespace-pre-wrap">
|
||||
{preview.main_config}
|
||||
|
||||
@@ -159,14 +159,14 @@ const reverseProxySchema = z
|
||||
const httpsSchema = z
|
||||
.object({
|
||||
enable_https: z.boolean(),
|
||||
cert_id: z.string(),
|
||||
cert_ids: z.array(z.string()),
|
||||
redirect_http: z.boolean(),
|
||||
})
|
||||
.superRefine((value, context) => {
|
||||
if (value.enable_https && !value.cert_id.trim()) {
|
||||
if (value.enable_https && value.cert_ids.length === 0) {
|
||||
context.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ['cert_id'],
|
||||
path: ['cert_ids'],
|
||||
message: '启用 HTTPS 时必须选择证书',
|
||||
});
|
||||
}
|
||||
@@ -542,7 +542,12 @@ function HTTPSSection({
|
||||
resolver: zodResolver(httpsSchema),
|
||||
defaultValues: {
|
||||
enable_https: route.enable_https,
|
||||
cert_id: route.cert_id ? String(route.cert_id) : '',
|
||||
cert_ids:
|
||||
route.cert_ids.length > 0
|
||||
? route.cert_ids.map((certID) => String(certID))
|
||||
: route.cert_id
|
||||
? [String(route.cert_id)]
|
||||
: [],
|
||||
redirect_http: route.redirect_http,
|
||||
},
|
||||
});
|
||||
@@ -550,12 +555,18 @@ function HTTPSSection({
|
||||
useEffect(() => {
|
||||
form.reset({
|
||||
enable_https: route.enable_https,
|
||||
cert_id: route.cert_id ? String(route.cert_id) : '',
|
||||
cert_ids:
|
||||
route.cert_ids.length > 0
|
||||
? route.cert_ids.map((certID) => String(certID))
|
||||
: route.cert_id
|
||||
? [String(route.cert_id)]
|
||||
: [],
|
||||
redirect_http: route.redirect_http,
|
||||
});
|
||||
}, [form, route]);
|
||||
|
||||
const watchedEnableHTTPS = form.watch('enable_https');
|
||||
const watchedCertIDs = form.watch('cert_ids');
|
||||
|
||||
return (
|
||||
<ConfigSectionShell
|
||||
@@ -571,7 +582,18 @@ function HTTPSSection({
|
||||
onSave(
|
||||
buildPayloadFromRoute(route, {
|
||||
enable_https: values.enable_https,
|
||||
cert_id: values.enable_https && values.cert_id ? Number(values.cert_id) : null,
|
||||
cert_id:
|
||||
values.enable_https &&
|
||||
values.cert_ids.some((value) => Number(value) > 0)
|
||||
? Number(
|
||||
values.cert_ids.find((value) => Number(value) > 0) ?? 0,
|
||||
)
|
||||
: null,
|
||||
cert_ids: values.enable_https
|
||||
? values.cert_ids
|
||||
.map((value) => Number(value))
|
||||
.filter((value) => Number.isFinite(value) && value > 0)
|
||||
: [],
|
||||
redirect_http: values.enable_https ? values.redirect_http : false,
|
||||
}),
|
||||
{ message: 'HTTPS 设置已保存。' },
|
||||
@@ -585,7 +607,7 @@ function HTTPSSection({
|
||||
onChange={(checked) => {
|
||||
form.setValue('enable_https', checked, { shouldDirty: true });
|
||||
if (!checked) {
|
||||
form.setValue('cert_id', '', { shouldDirty: true });
|
||||
form.setValue('cert_ids', [], { shouldDirty: true });
|
||||
form.setValue('redirect_http', false, { shouldDirty: true });
|
||||
}
|
||||
}}
|
||||
@@ -593,20 +615,30 @@ function HTTPSSection({
|
||||
|
||||
<ResourceField
|
||||
label="证书"
|
||||
error={form.formState.errors.cert_id?.message}
|
||||
error={form.formState.errors.cert_ids?.message}
|
||||
hint="请确保该证书能覆盖当前站点的全部域名。"
|
||||
>
|
||||
<ResourceSelect
|
||||
multiple
|
||||
size={Math.min(Math.max(certificates.length, 4), 8)}
|
||||
className="min-h-44"
|
||||
disabled={!watchedEnableHTTPS}
|
||||
{...form.register('cert_id')}
|
||||
{...form.register('cert_ids')}
|
||||
>
|
||||
<option value="">请选择证书</option>
|
||||
{certificates.map((certificate) => (
|
||||
<option key={certificate.id} value={certificate.id}>
|
||||
{certificate.name}
|
||||
{certificate.not_after
|
||||
? `${certificate.name} · ${certificate.not_after}`
|
||||
: certificate.name}
|
||||
</option>
|
||||
))}
|
||||
</ResourceSelect>
|
||||
{watchedEnableHTTPS && watchedCertIDs.length > 0 ? (
|
||||
<p className="text-xs leading-5 text-[var(--foreground-secondary)]">
|
||||
已选择 {watchedCertIDs.length} 张证书,发布时会校验证书集合是否覆盖全部域名。
|
||||
</p>
|
||||
) : null}
|
||||
</ResourceField>
|
||||
|
||||
<ToggleField
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
parseOriginUrl,
|
||||
parseOriginUrls,
|
||||
validateDomains,
|
||||
} from '@/features/proxy-routes/helpers';
|
||||
} from '@/features/proxy-routes/helpers';buyao
|
||||
import type { ProxyRouteItem } from '@/features/proxy-routes/types';
|
||||
import {
|
||||
PrimaryButton,
|
||||
|
||||
@@ -283,6 +283,7 @@ export function buildPayloadFromRoute(
|
||||
enabled: route.enabled,
|
||||
enable_https: route.enable_https,
|
||||
cert_id: route.cert_id,
|
||||
cert_ids: route.cert_ids,
|
||||
redirect_http: route.redirect_http,
|
||||
limit_conn_per_server: route.limit_conn_per_server,
|
||||
limit_conn_per_ip: route.limit_conn_per_ip,
|
||||
@@ -316,4 +317,3 @@ export function getWebsiteStatusBadges(route: ProxyRouteItem) {
|
||||
: { label: '缓存关闭', variant: 'warning' as const },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface ProxyRouteItem {
|
||||
enabled: boolean;
|
||||
enable_https: boolean;
|
||||
cert_id: number | null;
|
||||
cert_ids: number[];
|
||||
redirect_http: boolean;
|
||||
limit_conn_per_server: number;
|
||||
limit_conn_per_ip: number;
|
||||
@@ -48,6 +49,7 @@ export interface ProxyRouteMutationPayload {
|
||||
enabled: boolean;
|
||||
enable_https: boolean;
|
||||
cert_id: number | null;
|
||||
cert_ids?: number[];
|
||||
redirect_http: boolean;
|
||||
limit_conn_per_server?: number;
|
||||
limit_conn_per_ip?: number;
|
||||
|
||||
Reference in New Issue
Block a user