56 lines
4.3 KiB
JavaScript
56 lines
4.3 KiB
JavaScript
import {linkShared} from './helpers/shared-modules.mjs';
|
|
import {test} from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {readFile} from 'node:fs/promises';
|
|
import ts from 'typescript';
|
|
|
|
async function moduleUrl(path,imports={}){
|
|
let code=ts.transpileModule(await readFile(new URL('../src/lib/'+path+'.ts',import.meta.url),'utf8'),{compilerOptions:{module:ts.ModuleKind.ESNext,target:ts.ScriptTarget.ES2022}}).outputText;
|
|
for(const [name,url] of Object.entries(imports))code=code.replace("'"+name+"'",JSON.stringify(url));
|
|
return 'data:text/javascript;base64,'+Buffer.from(linkShared(code)).toString('base64');
|
|
}
|
|
const uaUrl=await moduleUrl('api/user-agent');
|
|
const {buildUserAgent,buildSdkUserAgent,userAgentSid}=await import(uaUrl);
|
|
const sdkUrl=await moduleUrl('api/sdk-headers');
|
|
const {clientHeaders}=await import(await moduleUrl('api/client-headers',{'./user-agent':uaUrl,'./sdk-headers':sdkUrl}));
|
|
|
|
// Generated by running the reference Go BuildXUserAgent function without changing its logic.
|
|
const samples=JSON.parse(await readFile(new URL('./fixtures/request-user-agents.json',import.meta.url),'utf8'));
|
|
for(const sample of samples)test('reference Go UA output matches '+sample.name,()=>{
|
|
assert.equal(buildUserAgent(sample.ua,sample.sid,sample.version),sample.expected);
|
|
});
|
|
|
|
test('existing X-User-Agent wins over SDK fields and network headers remain separate from credentials',()=>{
|
|
const xua='DevID=client-device;DevType=iPhone;SysType=h5_ios;Ver=2.0;BuildID=client;sid=client-sid';
|
|
const fields={sid:'sdk-sid',device_id:'sdk-device',device:'Android',device_fingerprint:'raw',fp_version:'3',app_version:'1.0.0'};
|
|
const headers=clientHeaders(new Headers({'User-Agent':' Browser UA ','X-User-Agent':xua,'X-Real-IP':'203.0.113.9','X-Forwarded-For':'203.0.113.8, 10.0.0.1','X-SDK-Common':Buffer.from(JSON.stringify(fields)).toString('base64'),Cookie:'drama_session=private',Authorization:'private'}));
|
|
assert.equal(headers['User-Agent'],'Browser UA');assert.equal(headers['X-User-Agent'],xua);assert.equal(headers['X-Real-IP'],'203.0.113.9');
|
|
assert.deepEqual(JSON.parse(Buffer.from(headers['X-SDK-Common'],'base64')),{sid:'sdk-sid',device_id:'sdk-device',app_version:'1.0.0'});
|
|
for(const key of ['Cookie','Authorization','X-Forwarded-For'])assert.equal(headers[key],undefined);
|
|
});
|
|
|
|
test('business drama_device pins DevID so SDK fingerprints cannot invalidate the guest token',()=>{
|
|
const xua='DevID=sdk-device;DevType=PC;SysType=h5_pc;Ver=1.0.0;BuildID=web;sid=sdk-sid';
|
|
const headers=clientHeaders(new Headers({'User-Agent':'Mozilla/5.0','X-User-Agent':xua,Cookie:'drama_session=secret; drama_device=business-device'}));
|
|
assert.equal(headers['X-User-Agent'],'DevID=business-device;DevType=PC;SysType=h5_pc;Ver=1.0.0;BuildID=web;sid=sdk-sid');
|
|
const sample=samples.find(item=>item.name==='iphone');
|
|
const fallback=clientHeaders(new Headers({'User-Agent':sample.ua,Cookie:'sid=reference-sid; drama_device=only-device'}));
|
|
assert.equal(fallback['X-User-Agent'],sample.expected,'SSR UA without DevID stays unchanged');
|
|
});
|
|
|
|
test('SSR and media fallback use the UA, SID cookie and first forwarded IP without a fabricated identity',()=>{
|
|
const sample=samples.find(item=>item.name==='iphone');
|
|
const headers=clientHeaders(new Headers({'User-Agent':sample.ua,'X-Real-IP':'invalid','X-Forwarded-For':'203.0.113.7, 10.0.0.1',Cookie:'sid=reference-sid; drama_device=business-device'}));
|
|
assert.equal(headers['X-User-Agent'],sample.expected);assert.equal(headers['X-Real-IP'],'203.0.113.7');
|
|
const empty=clientHeaders(undefined);assert.equal(empty['User-Agent'],undefined);assert.ok(!empty['X-User-Agent'].includes('DevID='));
|
|
assert.equal(userAgentSid('sid=first; _s_token_=second'),'first');
|
|
assert.equal(userAgentSid('_s_token_={"sid":"json-sid"}'),'json-sid');
|
|
assert.equal(userAgentSid('_s_token_=plain-sid'),'plain-sid');
|
|
});
|
|
|
|
test('browser SDK XUA uses the reference field order and cleans header delimiters without altering the snapshot',()=>{
|
|
const fields={device_id:'sdk-device',device:'Android',app_version:'2.3',device_brand:'Sam;sung',device_model:'model=1',sid:'sdk-sid'};
|
|
assert.equal(buildSdkUserAgent(fields),'DevID=sdk-device;DevType=Android;SysType=h5_android;Ver=2.3;BuildID=web;device_brand=Sam sung;device_model=model 1;sid=sdk-sid');
|
|
assert.equal(fields.device_brand,'Sam;sung');assert.equal(fields.device_model,'model=1');
|
|
});
|