如何使用 fetch 为 tRPC 查询编码查询参数

问题描述 投票:0回答:2

根据

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"}}}

知道为什么我构建的获取失败了吗?对象的编码/结构的正确格式是什么?

typescript next.js rpc trpc.io
2个回答
4
投票

不可能告诉你你的请求需要的确切结构,因为这取决于你如何设置 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


0
投票

当您使用

superjson
时,不要忘记在初始化tRPC客户端时将
transformer
添加为
superjson

© www.soinside.com 2019 - 2024. All rights reserved.