mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-09 11:48:18 +00:00
fix(dns): stop offering a port field that DoH entries discard
Xray ignores port for DoH/DoHL/DoQL, so valuesToWire deliberately stores none for an encrypted address and a non-standard port has to go inside the URL. The form kept offering the field anyway, pre-filled with the 53 from its own defaults: a port typed there was dropped on save and redrawn as 53 on reopen, which reads as the panel losing the value. Render the port field only where it is actually stored. DoT keeps it, since tls:// is not an encrypted-address scheme for this purpose. Closes #6403
This commit is contained in:
@@ -137,7 +137,13 @@ export default function DnsServerModal({
|
||||
onConfirm,
|
||||
}: DnsServerModalProps) {
|
||||
const { t } = useTranslation();
|
||||
const methods = useForm<DnsServerForm>({ defaultValues: defaultFormValues() });
|
||||
const methods = useForm<DnsServerForm>({
|
||||
defaultValues: defaultFormValues(),
|
||||
});
|
||||
const address = useWatch({ control: methods.control, name: 'address' }) ?? '';
|
||||
// Xray ignores port for DoH/DoHL/DoQL, so valuesToWire never stores one:
|
||||
// offering the field there discards whatever is typed into it.
|
||||
const portApplies = !isEncryptedDnsAddress(address);
|
||||
const domains = useWatch({ control: methods.control, name: 'domains' }) ?? [];
|
||||
const expectedIPs = useWatch({ control: methods.control, name: 'expectedIPs' }) ?? [];
|
||||
const unexpectedIPs = useWatch({ control: methods.control, name: 'unexpectedIPs' }) ?? [];
|
||||
@@ -168,13 +174,15 @@ export default function DnsServerModal({
|
||||
>
|
||||
<Input />
|
||||
</FormField>
|
||||
<FormField
|
||||
label={t('pages.inbounds.port')}
|
||||
name="port"
|
||||
rules={{ validate: rhfZodValidate(shape.port) }}
|
||||
>
|
||||
<InputNumber min={1} max={65535} />
|
||||
</FormField>
|
||||
{portApplies && (
|
||||
<FormField
|
||||
label={t('pages.inbounds.port')}
|
||||
name="port"
|
||||
rules={{ validate: rhfZodValidate(shape.port) }}
|
||||
>
|
||||
<InputNumber min={1} max={65535} />
|
||||
</FormField>
|
||||
)}
|
||||
<FormField label={t('pages.xray.dns.tag')} name="tag">
|
||||
<Input />
|
||||
</FormField>
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
|
||||
import DnsServerModal from '@/pages/xray/dns/DnsServerModal';
|
||||
import { renderWithProviders } from './test-utils';
|
||||
|
||||
describe('DnsServerModal port field', () => {
|
||||
it('hides the port for an encrypted address, whose port lives in the URL', () => {
|
||||
renderWithProviders(
|
||||
<DnsServerModal
|
||||
open
|
||||
server="https://dns.example.com/dns-query"
|
||||
isEdit
|
||||
onClose={() => {}}
|
||||
onConfirm={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.queryByLabelText('Port')).toBeNull();
|
||||
});
|
||||
|
||||
it('offers the port for a plain address and for DoT', () => {
|
||||
renderWithProviders(
|
||||
<DnsServerModal
|
||||
open
|
||||
server="tls://dns.example.com"
|
||||
isEdit
|
||||
onClose={() => {}}
|
||||
onConfirm={() => {}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(screen.getByLabelText('Port')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('drops the port field as soon as the address becomes a DoH URL', () => {
|
||||
renderWithProviders(
|
||||
<DnsServerModal open server="1.1.1.1" isEdit onClose={() => {}} onConfirm={() => {}} />,
|
||||
);
|
||||
|
||||
expect(screen.getByLabelText('Port')).toBeTruthy();
|
||||
fireEvent.change(screen.getByLabelText('Address'), {
|
||||
target: { value: 'https://dns.example.com/dns-query' },
|
||||
});
|
||||
expect(screen.queryByLabelText('Port')).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user