Skip to content

Commit

Permalink
make json-rpc server id handling spec-compliant (#807)
Browse files Browse the repository at this point in the history
* make json-rpc server id handling spec-compliant

* await response, remove error code

* add string id tests for json rpc server
  • Loading branch information
voliva authored Aug 26, 2024
1 parent 87eea09 commit 4b7208a
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 12 deletions.
34 changes: 23 additions & 11 deletions packages/chopsticks/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const httpLogger = defaultLogger.child({ name: 'http' })
const wsLogger = defaultLogger.child({ name: 'ws' })

const singleRequest = z.object({
id: z.number(),
id: z.optional(z.union([z.number().int(), z.string(), z.null()])),
jsonrpc: z.literal('2.0'),
method: z.string(),
params: z.array(z.any()).default([]),
Expand Down Expand Up @@ -91,6 +91,21 @@ export const createServer = async (handler: Handler, port: number) => {
},
}

const safeHandleRequest = async (request: z.infer<typeof singleRequest>) => {
try {
const result = await handler(request, emptySubscriptionManager)
return request.id === undefined ? undefined : { id: request.id, jsonrpc: '2.0', result }
} catch (err: any) {
return {
jsonrpc: '2.0',
id: request.id,
error: {
message: err.message,
},
}
}
}

const server = http.createServer(async (req, res) => {
if (req.method === 'OPTIONS') {
return respond(res)
Expand All @@ -112,24 +127,21 @@ export const createServer = async (handler: Handler, port: number) => {

let response: any
if (Array.isArray(parsed.data)) {
response = await Promise.all(
parsed.data.map((req) => {
const result = handler(req, emptySubscriptionManager)
return { id: req.id, jsonrpc: '2.0', result }
}),
)
response = await Promise.all(parsed.data.map(safeHandleRequest))
response = response.filter((r) => r !== undefined)
} else {
const result = await handler(parsed.data, emptySubscriptionManager)
response = { id: parsed.data.id, jsonrpc: '2.0', result }
response = await safeHandleRequest(parsed.data)
}

respond(res, JSON.stringify(response))
if (response !== undefined) {
respond(res, JSON.stringify(response))
}
} catch (err: any) {
respond(
res,
JSON.stringify({
jsonrpc: '2.0',
id: 1,
id: null,
error: {
message: err.message,
},
Expand Down
20 changes: 19 additions & 1 deletion packages/e2e/src/http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe('http.server', () => {
"error": {
"message": "Only POST method is supported",
},
"id": 1,
"id": null,
"jsonrpc": "2.0",
}
`,
Expand All @@ -115,5 +115,23 @@ describe('http.server', () => {
},
).end(body)
}

{
// Accepts string ids
const id = 'lorem ipsum dolor sit amet'
const res = await fetch(`http://localhost:${port}`, {
method: 'POST',
body: JSON.stringify({ id, jsonrpc: '2.0', method: 'chain_getBlockHash', params: [] }),
})
expect(await res.json()).toMatchInlineSnapshot(
`
{
"id": "${id}",
"jsonrpc": "2.0",
"result": "0x0df086f32a9c3399f7fa158d3d77a1790830bd309134c5853718141c969299c7",
}
`,
)
}
})
})

0 comments on commit 4b7208a

Please sign in to comment.