根据
tRPC
s documentation,查询参数必须遵循这种格式
myQuery?input=${encodeURIComponent(JSON.stringify(input))}
我有这个程序:
hello: publicProcedure
.input(z.object({ text: z.string() }))
.output(z.object({ greeting: z.string() }))
.query(({ input }) => {
return {
greeting: `Hello ${input.text}`,
};
}),
手动构建的URL返回错误:
const data = {text: "my message"}
const res = await fetch('http://localhost:3000/api/trpc/example.hello?batch=1&input='+encodeURIComponent(JSON.stringify(data)), { method: 'GET' });
const body = await res.json();
console.log(body);
错误表明查询参数没有正确编码?知道出了什么问题吗?使用客户端,它有效:
const test = api.example.hello.useQuery({ text: "my message" });
{
"error": {
"json": {
"message": "[\n {\n \"code\": \"invalid_type\",\n \"expected\": \"object\",\n \"received\": \"undefined\",\n \"path\": [],\n \"message\": \"Required\"\n }\n]",
"code": -32600,
"data": {
"code": "BAD_REQUEST",
"httpStatus": 400,
"stack": "TRPCError: [\n {\n \"code\": \"invalid_type\",\n \"expected\": \"object\",\n \"received\": \"undefined\",\n \"path\": [],\n \"message\": \"Required\"\n }\n]\n at inputMiddleware (file:///Users/michael/Projects/t3/test/my-t3-app/node_modules/@trpc/server/dist/index.mjs:252:19)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (node:internal/process/task_queues:96:5)\n at async callRecursive (file:///Users/michael/Projects/t3/test/my-t3-app/node_modules/@trpc/server/dist/index.mjs:419:32)\n at async resolve (file:///Users/michael/Projects/t3/test/my-t3-app/node_modules/@trpc/server/dist/index.mjs:447:24)\n at async file:///Users/michael/Projects/t3/test/my-t3-app/node_modules/@trpc/server/dist/resolveHTTPResponse-a3869d43.mjs:123:32\n at async Promise.all (index 0)\n at async resolveHTTPResponse (file:///Users/michael/Projects/t3/test/my-t3-app/node_modules/@trpc/server/dist/resolveHTTPResponse-a3869d43.mjs:120:28)\n at async nodeHTTPRequestHandler (file:///Users/michael/Projects/t3/test/my-t3-app/node_modules/@trpc/server/dist/nodeHTTPRequestHandler-e46cee59.mjs:51:20)\n at async file:///Users/michael/Projects/t3/test/my-t3-app/node_modules/@trpc/server/dist/adapters/next.mjs:40:9\n at async Object.apiResolver (/Users/michael/Projects/t3/test/my-t3-app/node_modules/next/dist/server/api-utils/node.js:363:9)\n at async DevServer.runApi (/Users/michael/Projects/t3/test/my-t3-app/node_modules/next/dist/server/next-server.js:487:9)\n at async Object.fn (/Users/michael/Projects/t3/test/my-t3-app/node_modules/next/dist/server/next-server.js:749:37)\n at async Router.execute (/Users/michael/Projects/t3/test/my-t3-app/node_modules/next/dist/server/router.js:253:36)\n at async DevServer.run (/Users/michael/Projects/t3/test/my-t3-app/node_modules/next/dist/server/base-server.js:384:29)\n at async DevServer.run (/Users/michael/Projects/t3/test/my-t3-app/node_modules/next/dist/server/dev/next-dev-server.js:741:20)\n at async DevServer.handleRequest (/Users/michael/Projects/t3/test/my-t3-app/node_modules/next/dist/server/base-server.js:322:20)",
"path": "example.hello"
}
}
}
}
我检查了使用客户端时浏览器发送的查询(
const test = api.example.hello.useQuery({ text: "my message" });
)。下面的查询,它成功.
http://localhost:3000/api/trpc/example.hello?batch=1&input=%7B%220%22%3A%7B%22json%22%3A%7B%22text%22%3A%22my%20message%22%7D%7D%7D
如果我解码输入的查询参数,我会看到
{"0":{"json":{"text":"my message"}}}
如果我以相同的方式编码我的构造数据对象,查询仍然失败:
const data = {"0":{"json":{"text":"my message"}}}
const res = await fetch('http://localhost:3000/api/trpc/example.hello?batch=1&input='+encodeURIComponent(JSON.stringify(data)), { method: 'GET' });
const body = await res.json();
console.log(body);
0
似乎有必要启用 b/c 批处理?但是json
领域似乎很奇怪。
{"0":{"json":{"text":"my message"}}}
知道为什么我构建的获取失败了吗?对象的编码/结构的正确格式是什么?
不可能告诉你你的请求需要的确切结构,因为这取决于你如何设置 tRPC,特别是你的链接和转换器。我也不知道你的请求是否结构正确,因为你没有为每个请求显示
data
里面的内容。
话虽如此,让我们以更一般的方式来看它。
您请求中所需的
json
键几乎可以肯定是因为您已将superjson设置为您的transformer。这是大多数使用 tRPC 的模板中的标准,例如 Create T3 App 或 tRPC 的 GitHub 中的示例项目,因此除非您从头开始构建您的应用程序,否则您可能会启用此功能。 superjson 的目的是为了更容易发送一些使用常规 JSON 比较棘手的数据类型,例如 Dates。
关于
batch
,你写的都是正确的。但是,您也可以修改此行为。它由 ending link 决定。如果你不想批量,你可以使用httpLink
代替httpBatchLink
(但在大多数情况下建议使用批量链接)。
现在让我们看一些示例请求(我在这里没有对它们进行 URI 编码以使其更易于阅读)
superjson,httpBatchLink:
http://localhost:3000/api/trpc/example.hello?batch=1&input={"0":{"json":{"text":"from tRPC"}}}
superjson,http链接:
http://localhost:3000/api/trpc/example.hello?input={"json":{"text":"from tRPC"}}
没有superjson,httpBatchLink:
http://localhost:3000/api/trpc/example.hello?batch=1&input={"0":{"text":"from tRPC"}}
没有superjson,http链接:
http://localhost:3000/api/trpc/example.hello?input={"text":"from tRPC"}
如果您想以更“标准的 REST”方式与您的 tRPC API 通信,可以使用 trpc-openapi。
当您使用
superjson
时,不要忘记在初始化tRPC客户端时将transformer
添加为superjson
。