|
@@ -9,6 +9,7 @@ import {
|
|
|
normalizeXhttpForWire,
|
|
normalizeXhttpForWire,
|
|
|
validateRealityTarget,
|
|
validateRealityTarget,
|
|
|
} from '@/lib/xray/stream-wire-normalize';
|
|
} from '@/lib/xray/stream-wire-normalize';
|
|
|
|
|
+import { InboundFormSchema } from '@/schemas/forms/inbound-form';
|
|
|
import type { InboundFormValues } from '@/schemas/forms/inbound-form';
|
|
import type { InboundFormValues } from '@/schemas/forms/inbound-form';
|
|
|
|
|
|
|
|
describe('validateRealityTarget', () => {
|
|
describe('validateRealityTarget', () => {
|
|
@@ -150,6 +151,28 @@ describe('normalizeStreamSettingsForWire reality', () => {
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+describe('normalizeStreamSettingsForWire tls', () => {
|
|
|
|
|
+ it('drops empty uTLS fingerprints from inbound and outbound TLS shapes', () => {
|
|
|
|
|
+ const out = normalizeStreamSettingsForWire({
|
|
|
|
|
+ network: 'hysteria',
|
|
|
|
|
+ security: 'tls',
|
|
|
|
|
+ tlsSettings: {
|
|
|
|
|
+ fingerprint: '',
|
|
|
|
|
+ settings: {
|
|
|
|
|
+ fingerprint: '',
|
|
|
|
|
+ echConfigList: '',
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ }, { side: 'inbound' });
|
|
|
|
|
+
|
|
|
|
|
+ const tls = out.tlsSettings as Record<string, unknown>;
|
|
|
|
|
+ const settings = tls.settings as Record<string, unknown>;
|
|
|
|
|
+ expect(tls).not.toHaveProperty('fingerprint');
|
|
|
|
|
+ expect(settings).not.toHaveProperty('fingerprint');
|
|
|
|
|
+ expect(settings.echConfigList).toBe('');
|
|
|
|
|
+ });
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
describe('inbound formValuesToWirePayload integration', () => {
|
|
describe('inbound formValuesToWirePayload integration', () => {
|
|
|
it('emits lean stream-one xhttp + sockopt on save', () => {
|
|
it('emits lean stream-one xhttp + sockopt on save', () => {
|
|
|
const values = {
|
|
const values = {
|
|
@@ -209,6 +232,51 @@ describe('inbound formValuesToWirePayload integration', () => {
|
|
|
const realitySettings = reality.settings as Record<string, unknown>;
|
|
const realitySettings = reality.settings as Record<string, unknown>;
|
|
|
expect(realitySettings.publicKey).toBe('pub');
|
|
expect(realitySettings.publicKey).toBe('pub');
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ it('accepts Hysteria TLS with uTLS None and omits fingerprint on save', () => {
|
|
|
|
|
+ const values = {
|
|
|
|
|
+ remark: 'hy2',
|
|
|
|
|
+ enable: true,
|
|
|
|
|
+ port: 443,
|
|
|
|
|
+ listen: '',
|
|
|
|
|
+ tag: 'hy2-443',
|
|
|
|
|
+ expiryTime: 0,
|
|
|
|
|
+ sniffing: { enabled: false },
|
|
|
|
|
+ up: 0,
|
|
|
|
|
+ down: 0,
|
|
|
|
|
+ total: 0,
|
|
|
|
|
+ trafficReset: 'never',
|
|
|
|
|
+ lastTrafficResetTime: 0,
|
|
|
|
|
+ nodeId: null,
|
|
|
|
|
+ protocol: 'hysteria',
|
|
|
|
|
+ settings: { version: 2, clients: [] },
|
|
|
|
|
+ streamSettings: {
|
|
|
|
|
+ network: 'hysteria',
|
|
|
|
|
+ security: 'tls',
|
|
|
|
|
+ hysteriaSettings: {
|
|
|
|
|
+ version: 2,
|
|
|
|
|
+ auth: 'auth',
|
|
|
|
|
+ udpIdleTimeout: 60,
|
|
|
|
|
+ },
|
|
|
|
|
+ tlsSettings: {
|
|
|
|
|
+ alpn: ['h3'],
|
|
|
|
|
+ settings: {
|
|
|
|
|
+ fingerprint: '',
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const parsed = InboundFormSchema.safeParse(values);
|
|
|
|
|
+ expect(parsed.success).toBe(true);
|
|
|
|
|
+ if (!parsed.success) throw parsed.error;
|
|
|
|
|
+
|
|
|
|
|
+ const payload = formValuesToWirePayload(parsed.data);
|
|
|
|
|
+ const stream = JSON.parse(payload.streamSettings) as Record<string, unknown>;
|
|
|
|
|
+ const tls = stream.tlsSettings as Record<string, unknown>;
|
|
|
|
|
+ const settings = tls.settings as Record<string, unknown>;
|
|
|
|
|
+ expect(settings).not.toHaveProperty('fingerprint');
|
|
|
|
|
+ });
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
describe('freedom outbound sockopt wire payload', () => {
|
|
describe('freedom outbound sockopt wire payload', () => {
|