Skip to content

Commit d3b4900

Browse files
authored
feat(server): check prefix inside handlers (#295)
Mean you don't need manually check prefix, oRPC do that for you Before: ```ts export async function fetch(request: Request): Promise<Response> { const url = new URL(request.url) if (url.pathname.startsWith('/rpc')) { const { response } = await handler.handle(request, { prefix: '/rpc', context: {} // Provide initial context if needed }) if (response) return response } return new Response('Not found', { status: 404 }) } ``` After: ```ts export async function fetch(request: Request): Promise<Response> { const { matched, response } = await handler.handle(request, { prefix: '/rpc', context: {} // Provide initial context if needed }) if (matched) { return response } return new Response('Not found', { status: 404 }) } ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Streamlined request processing across various integrations to ensure consistent API and RPC responses, including reliable handling of unmatched requests. - **Tests** - Added coverage to verify proper behavior when an invalid request prefix is provided. - **Chores** - Updated URL formatting to standardize trailing slash removal and removed an unused utility for cleaner maintenance. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 6896c4f commit d3b4900

File tree

13 files changed

+98
-105
lines changed

13 files changed

+98
-105
lines changed

apps/content/docs/integrations/bun.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,13 @@ const handler = new RPCHandler(router, {
2121

2222
Bun.serve({
2323
async fetch(request: Request) {
24-
const url = new URL(request.url)
24+
const { matched, response } = await handler.handle(request, {
25+
prefix: '/rpc',
26+
context: {} // Provide initial context if needed
27+
})
2528

26-
if (url.pathname.startsWith('/rpc')) {
27-
const { response } = await handler.handle(request, {
28-
prefix: '/rpc',
29-
context: {} // Provide initial context if needed
30-
})
31-
32-
if (response) {
33-
return response
34-
}
29+
if (matched) {
30+
return response
3531
}
3632

3733
return new Response('Not found', { status: 404 })

apps/content/docs/integrations/cloudflare-workers.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,13 @@ const handler = new RPCHandler(router, {
2121

2222
export default {
2323
async fetch(request: Request, env: any, ctx: ExecutionContext): Promise<Response> {
24-
const url = new URL(request.url)
24+
const { matched, response } = await handler.handle(request, {
25+
prefix: '/rpc',
26+
context: {} // Provide initial context if needed
27+
})
2528

26-
if (url.pathname.startsWith('/rpc')) {
27-
const { response } = await handler.handle(request, {
28-
prefix: '/rpc',
29-
context: {} // Provide initial context if needed
30-
})
31-
32-
if (response) {
33-
return response
34-
}
29+
if (matched) {
30+
return response
3531
}
3632

3733
return new Response('Not found', { status: 404 })

apps/content/docs/integrations/deno.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,13 @@ const handler = new RPCHandler(router, {
2020
})
2121

2222
Deno.serve(async (request) => {
23-
const url = new URL(request.url)
23+
const { matched, response } = await handler.handle(request, {
24+
prefix: '/rpc',
25+
context: {} // Provide initial context if needed
26+
})
2427

25-
if (url.pathname.startsWith('/rpc')) {
26-
const { response } = await handler.handle(request, {
27-
prefix: '/rpc',
28-
context: {} // Provide initial context if needed
29-
})
30-
31-
if (response) {
32-
return response
33-
}
28+
if (matched) {
29+
return response
3430
}
3531

3632
return new Response('Not found', { status: 404 })

apps/content/docs/integrations/fetch-server.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,13 @@ const handler = new RPCHandler(router, {
2020
})
2121

2222
export async function fetch(request: Request): Promise<Response> {
23-
const url = new URL(request.url)
23+
const { matched, response } = await handler.handle(request, {
24+
prefix: '/rpc',
25+
context: {} // Provide initial context if needed
26+
})
2427

25-
if (url.pathname.startsWith('/rpc')) {
26-
const { response } = await handler.handle(request, {
27-
prefix: '/rpc',
28-
context: {} // Provide initial context if needed
29-
})
30-
31-
if (response)
32-
return response
28+
if (matched) {
29+
return response
3330
}
3431

3532
return new Response('Not found', { status: 404 })

apps/content/docs/integrations/node.md

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,13 @@ const handler = new RPCHandler(router, {
2525
})
2626

2727
const server = createServer(async (req, res) => {
28-
if (req.url.startsWith('/rpc')) {
29-
const { matched } = await handler.handle(req, res, {
30-
prefix: '/rpc',
31-
context: {} // Provide initial context if needed
32-
})
33-
34-
if (matched) {
35-
return
36-
}
28+
const { matched } = await handler.handle(req, res, {
29+
prefix: '/rpc',
30+
context: {} // Provide initial context if needed
31+
})
32+
33+
if (matched) {
34+
return
3735
}
3836

3937
res.statusCode = 404
@@ -64,15 +62,13 @@ const server = createSecureServer({
6462
key: fs.readFileSync('key.pem'),
6563
cert: fs.readFileSync('cert.pem'),
6664
}, async (req, res) => {
67-
if (req.url.startsWith('/rpc')) {
68-
const { matched } = await handler.handle(req, res, {
69-
prefix: '/rpc',
70-
context: {}, // Provide initial context if needed
71-
})
72-
73-
if (matched) {
74-
return
75-
}
65+
const { matched } = await handler.handle(req, res, {
66+
prefix: '/rpc',
67+
context: {}, // Provide initial context if needed
68+
})
69+
70+
if (matched) {
71+
return
7672
}
7773

7874
res.statusCode = 404

apps/content/docs/openapi/openapi-handler.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,13 @@ const handler = new OpenAPIHandler(router, {
7777
})
7878

7979
export default async function fetch(request: Request) {
80-
const url = new URL(request.url)
80+
const { matched, response } = await handler.handle(request, {
81+
prefix: '/api',
82+
context: {} // Add initial context if needed
83+
})
8184

82-
if (url.pathname.startsWith('/api')) {
83-
const result = await handler.handle(request, {
84-
prefix: '/api',
85-
context: {} // Add initial context if needed
86-
})
87-
88-
if (result.matched)
89-
return result.response
85+
if (matched) {
86+
response
9087
}
9188

9289
return new Response('Not Found', { status: 404 })

apps/content/docs/openapi/scalar.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,12 @@ const openAPIGenerator = new OpenAPIGenerator({
3030
})
3131

3232
const server = createServer(async (req, res) => {
33-
if (req.url?.startsWith('/api')) {
34-
const { matched } = await openAPIHandler.handle(req, res, {
35-
prefix: '/api',
36-
})
33+
const { matched } = await openAPIHandler.handle(req, res, {
34+
prefix: '/api',
35+
})
3736

38-
if (matched) {
39-
return
40-
}
37+
if (matched) {
38+
return
4139
}
4240

4341
if (req.url === '/spec.json') {

apps/content/docs/rpc-handler.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,13 @@ const handler = new RPCHandler(router, {
5555
})
5656

5757
export default async function fetch(request: Request) {
58-
const url = new URL(request.url)
58+
const { matched, response } = await handler.handle(request, {
59+
prefix: '/rpc',
60+
context: {} // Provide initial context if required
61+
})
5962

60-
if (url.pathname.startWith('/rpc')) {
61-
const result = await handler.handle(request, {
62-
prefix: '/rpc',
63-
context: {} // Provide initial context if required
64-
})
65-
66-
if (result.matched) {
67-
return result.response
68-
}
63+
if (matched) {
64+
return response
6965
}
7066

7167
return new Response('Not Found', { status: 404 })

packages/client/src/adapters/standard/rpc-link-codec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { StandardHeaders, StandardLazyResponse, StandardRequest } from '@or
22
import type { ClientContext, ClientOptions } from '../../types'
33
import type { StandardRPCSerializer } from './rpc-serializer'
44
import type { StandardLinkCodec } from './types'
5-
import { isAsyncIteratorObject, stringifyJSON, trim, value, type Value } from '@orpc/shared'
5+
import { isAsyncIteratorObject, stringifyJSON, value, type Value } from '@orpc/shared'
66
import { ORPCError } from '../../error'
77

88
type HTTPMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
@@ -79,7 +79,7 @@ export class StandardRPCLinkCodec<T extends ClientContext> implements StandardLi
7979
const expectedMethod = await value(this.expectedMethod, options, path, input)
8080
const headers = { ...await value(this.headers, options, path, input) }
8181
const baseUrl = await value(this.baseUrl, options, path, input)
82-
const url = new URL(`${trim(baseUrl.toString(), '/')}/${path.map(encodeURIComponent).join('/')}`)
82+
const url = new URL(`${baseUrl.toString().replace(/\/$/, '')}/${path.map(encodeURIComponent).join('/')}`)
8383

8484
if (options.lastEventId !== undefined) {
8585
if (Array.isArray(headers['last-event-id'])) {

packages/server/src/adapters/standard/handler.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,4 +340,22 @@ describe('standardHandler', () => {
340340
expect(init).toHaveBeenCalledOnce()
341341
expect(init).toHaveBeenCalledWith(options)
342342
})
343+
344+
it('should check prefix first', async () => {
345+
const result = await handler.handle({
346+
raw: { adapter: '' },
347+
method: 'GET',
348+
headers: {
349+
Accept: 'application/json',
350+
},
351+
url: new URL('http://localhost/users/1'),
352+
body: vi.fn(),
353+
signal,
354+
}, {
355+
context: { db: 'postgres' },
356+
prefix: '/invalid',
357+
})
358+
359+
expect(result).toEqual({ matched: false, response: undefined })
360+
})
343361
})

0 commit comments

Comments
 (0)