Skip to content

Commit e42e8e6

Browse files
committed
fix: move domain access tracking from middleware to query handlers
1 parent ab32e7c commit e42e8e6

File tree

2 files changed

+55
-35
lines changed

2 files changed

+55
-35
lines changed

server/routers/domain.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ import { getPricingForTld } from "@/server/services/pricing";
2020
import { getRegistration } from "@/server/services/registration";
2121
import { getOrCreateScreenshotBlobUrl } from "@/server/services/screenshot";
2222
import { getSeo } from "@/server/services/seo";
23-
import { createTRPCRouter, domainProcedure } from "@/trpc/init";
23+
import {
24+
createTRPCRouter,
25+
domainProcedure,
26+
trackDomainAccess,
27+
} from "@/trpc/init";
2428

2529
const DomainInputSchema = z
2630
.object({ domain: z.string().min(1) })
@@ -35,7 +39,10 @@ export const domainRouter = createTRPCRouter({
3539
.meta({ service: "registration" })
3640
.input(DomainInputSchema)
3741
.output(RegistrationSchema)
38-
.query(({ input }) => getRegistration(input.domain)),
42+
.query(({ input }) => {
43+
trackDomainAccess(input.domain);
44+
return getRegistration(input.domain);
45+
}),
3946
pricing: domainProcedure
4047
.meta({ service: "pricing" })
4148
.input(DomainInputSchema)
@@ -45,27 +52,42 @@ export const domainRouter = createTRPCRouter({
4552
.meta({ service: "dns" })
4653
.input(DomainInputSchema)
4754
.output(DnsResolveResultSchema)
48-
.query(({ input }) => resolveAll(input.domain)),
55+
.query(({ input }) => {
56+
trackDomainAccess(input.domain);
57+
return resolveAll(input.domain);
58+
}),
4959
hosting: domainProcedure
5060
.meta({ service: "hosting" })
5161
.input(DomainInputSchema)
5262
.output(HostingSchema)
53-
.query(({ input }) => detectHosting(input.domain)),
63+
.query(({ input }) => {
64+
trackDomainAccess(input.domain);
65+
return detectHosting(input.domain);
66+
}),
5467
certificates: domainProcedure
5568
.meta({ service: "certs" })
5669
.input(DomainInputSchema)
5770
.output(CertificatesSchema)
58-
.query(({ input }) => getCertificates(input.domain)),
71+
.query(({ input }) => {
72+
trackDomainAccess(input.domain);
73+
return getCertificates(input.domain);
74+
}),
5975
headers: domainProcedure
6076
.meta({ service: "headers" })
6177
.input(DomainInputSchema)
6278
.output(HttpHeadersResponseSchema)
63-
.query(({ input }) => probeHeaders(input.domain)),
79+
.query(({ input }) => {
80+
trackDomainAccess(input.domain);
81+
return probeHeaders(input.domain);
82+
}),
6483
seo: domainProcedure
6584
.meta({ service: "seo" })
6685
.input(DomainInputSchema)
6786
.output(SeoResponseSchema)
68-
.query(({ input }) => getSeo(input.domain)),
87+
.query(({ input }) => {
88+
trackDomainAccess(input.domain);
89+
return getSeo(input.domain);
90+
}),
6991
favicon: domainProcedure
7092
.meta({ service: "favicon" })
7193
.input(DomainInputSchema)

trpc/init.ts

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -95,40 +95,38 @@ const withRatelimit = t.middleware(async ({ ctx, next, meta }) => {
9595
return next();
9696
});
9797

98-
/**
99-
* Middleware to record domain access for decay calculation.
100-
* Expects input to have a `domain` field containing the domain string.
101-
*/
102-
const withAccess = t.middleware(async ({ input, next }) => {
103-
// Extract domain from input and record access if it's a valid registrable domain
104-
const domain =
105-
typeof input === "object" &&
106-
input !== null &&
107-
"domain" in input &&
108-
typeof input.domain === "string"
109-
? input.domain
110-
: null;
111-
112-
if (domain) {
113-
const registrable = toRegistrableDomain(domain);
114-
if (registrable) {
115-
recordDomainAccess(registrable);
116-
}
117-
}
118-
119-
return next();
120-
});
121-
12298
/**
12399
* Public procedure with logging.
124100
* Use this for all public endpoints (e.g. health check, etc).
125101
*/
126102
export const publicProcedure = t.procedure.use(withLogging);
127103

128104
/**
129-
* Domain-specific procedure with rate limiting and access tracking.
105+
* Domain-specific procedure with rate limiting.
130106
* Use this for all domain data endpoints (dns, hosting, seo, etc).
107+
*
108+
* Note: Access tracking is done in the query handler, not middleware,
109+
* because the input hasn't been parsed yet at the middleware stage.
110+
*/
111+
export const domainProcedure = publicProcedure.use(withRatelimit);
112+
113+
/**
114+
* Helper to track domain access in query handlers.
115+
* Call this at the start of domain-related query handlers.
116+
*
117+
* @param domain - The domain from the input
118+
* @example
119+
* ```ts
120+
* .query(({ input }) => {
121+
* trackDomainAccess(input.domain);
122+
* return getSeo(input.domain);
123+
* })
124+
* ```
131125
*/
132-
export const domainProcedure = publicProcedure
133-
.use(withRatelimit)
134-
.use(withAccess);
126+
export function trackDomainAccess(domain: string): void {
127+
const registrable = toRegistrableDomain(domain);
128+
if (registrable) {
129+
console.debug(`[trpc] recording access for domain: ${registrable}`);
130+
recordDomainAccess(registrable);
131+
}
132+
}

0 commit comments

Comments
 (0)