feat: Add client fingerprint properties (tlsJA4, h2Fingerprint, ohFingerprint) #1248
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Adds three new properties to the
ClientInfoobject to bring the JavaScript SDK to parity with the Rust and Go SDKs for client fingerprinting capabilities:tlsJA4- JA4 TLS fingerprint (human-readable string format)h2Fingerprint- HTTP/2 fingerprint for HTTP/2 connectionsohFingerprint- Original Header fingerprint based on header order/presenceImplementation
The implementation follows the existing pattern established by
tlsJA3MD5and otherClientInfoproperties, spanning four layers:1. WASM Host Import (
runtime/fastly/host-api/fastly.h)Added declarations for the three new host calls:
2. C++ Host API Wrapper (
runtime/fastly/host-api/host_api_fastly.h+host_api.cpp)Added wrapper functions that handle buffer allocation, error conversion, and optional-none cases:
3. JavaScript Bindings (
runtime/fastly/builtins/fetch-event.h+fetch-event.cpp)ClientInfo::Slotsenum:JA4,H2Fingerprint,OHFingerprinttls_ja4_get,h2_fingerprint_get,oh_fingerprint_getClientInfo::properties[]4. TypeScript Types (
types/globals.d.ts)Added type declarations to the
ClientInfointerface:Files Changed
runtime/fastly/host-api/fastly.hruntime/fastly/host-api/host_api_fastly.hruntime/fastly/host-api/host_api.cppruntime/fastly/builtins/fetch-event.hruntime/fastly/builtins/fetch-event.cpptypes/globals.d.tsCHANGELOG.mdTesting
Local Build
Built the js-compute-runtime from source:
cd js-compute-runtime/runtime/fastly ./build-release.shThis compiles the C++ runtime (StarlingMonkey/SpiderMonkey) and outputs
fastly.wasmto the repo root (js-compute-runtime/fastly.wasm).Local Test Service
Created a separate test Compute service (
js-test/) that links to the local build:Directory structure:
js-test/package.json - Uses
file:protocol to link to local build:{ "dependencies": { "@fastly/js-compute": "file:../js-compute-runtime" }, "scripts": { "build": "js-compute-runtime src/index.js bin/main.wasm" } }When
npm installruns, it symlinksnode_modules/@fastly/js-compute→../js-compute-runtime, so the test service uses our modified runtime.js-test/src/index.js:
Build and Run Locally
Local results:
ClientInfoobjectnulllocally (expected - Viceroy doesn't do TLS termination)Edge Deployment
Deployed to Fastly edge and verified all fingerprints return real values:
Test endpoint: https://certainly-well-stingray.edgecompute.app/
Sample response:
{ "clientIP": "xxx.xxx.xxx.xxx", "tlsJA3MD5": "cd08e31494f9531f560d64c695473da9", "tlsJA4": "t13d1517h2_8daaf6152771_b0da82dd1658", "h2Fingerprint": "3:100;4:10485760;2:0|1048510465|0|m,s,a,p", "ohFingerprint": "RkRGRjAwMDEwMDAw...", "tlsProtocol": "TLSv1.3", "tlsCipher": "TLS_AES_128_GCM_SHA256" }Integration Tests
Added integration tests for the three new properties in
integration-tests/js-compute/fixtures/app/src/client.js:/client/tlsJA4nulllocally,stringon edge/client/h2Fingerprintnulllocally,nullorstringon edge (HTTP/1.1 connections won't have h2 fingerprint)/client/ohFingerprintnulllocally,stringon edgeTests follow the existing pattern for other
ClientInfoTLS properties (tlsJA3MD5,tlsProtocol, etc.).Run locally:
npm run test:integration -- --local "/client/" Results: ✔ GET /client/tlsJA3MD5 ✔ GET /client/tlsClientHello ✔ GET /client/tlsClientCertificate ✔ GET /client/tlsCipherOpensslName ✔ GET /client/tlsProtocol ✔ GET /client/tlsJA4 ✔ GET /client/h2Fingerprint ✔ GET /client/ohFingerprintChecklist
tlsJA3MD5)