本文へスキップ
バージョン:11.x

HTTP RPC仕様書

メソッド <-> 型マッピング

HTTPメソッドマッピング備考
GET.query()クエリパラメータにJSON文字列化された入力。
例: myQuery?input=${encodeURIComponent(JSON.stringify(input))}
POST.mutation()POSTボディとして入力。
該当なし.subscription()HTTPトランスポートではサブスクリプションはサポートされていません

ネストされたプロシージャへのアクセス

ネストされたプロシージャはドットで区切られます。そのため、下記のbyIdへのリクエストは/api/trpc/post.byIdへのリクエストになります。

ts
export const appRouter = router({
post: router({
byId: publicProcedure.input(String).query(async (opts) => {
// [...]
}),
}),
});
ts
export const appRouter = router({
post: router({
byId: publicProcedure.input(String).query(async (opts) => {
// [...]
}),
}),
});

バッチ処理

バッチ処理では、同じHTTPメソッドのすべてのパラレルなプロシージャ呼び出しをデータローダーを使用して1つのリクエストにまとめます。

  • 呼び出されたプロシージャの名前は、pathnameでコンマ(,)で結合されます。
  • 入力パラメータは、Record<number, unknown>の形をしたinputというクエリパラメータとして送信されます。
  • また、batch=1をクエリパラメータとして渡す必要があります。
  • レスポンスに異なるステータスがある場合、207 Multi-Statusを返します(例:1つの呼び出しがエラーになり、1つが成功した場合)。

バッチ処理の例:リクエスト

/api/trpcで公開されているこのようなルーターの場合:

server/router.ts
tsx
export const appRouter = t.router({
postById: t.procedure.input(String).query(async (opts) => {
const post = await opts.ctx.post.findUnique({
where: { id: opts.input },
});
return post;
}),
relatedPosts: t.procedure.input(String).query(async (opts) => {
const posts = await opts.ctx.findRelatedPostsById(opts.input);
return posts;
}),
});
server/router.ts
tsx
export const appRouter = t.router({
postById: t.procedure.input(String).query(async (opts) => {
const post = await opts.ctx.post.findUnique({
where: { id: opts.input },
});
return post;
}),
relatedPosts: t.procedure.input(String).query(async (opts) => {
const posts = await opts.ctx.findRelatedPostsById(opts.input);
return posts;
}),
});

…そして、Reactコンポーネントでこのように定義された2つのクエリ:

MyComponent.tsx
tsx
export function MyComponent() {
const post1 = trpc.postById.useQuery('1');
const relatedPosts = trpc.relatedPosts.useQuery('1');
return (
<pre>
{JSON.stringify(
{
post1: post1.data ?? null,
relatedPosts: relatedPosts.data ?? null,
},
null,
4,
)}
</pre>
);
}
MyComponent.tsx
tsx
export function MyComponent() {
const post1 = trpc.postById.useQuery('1');
const relatedPosts = trpc.relatedPosts.useQuery('1');
return (
<pre>
{JSON.stringify(
{
post1: post1.data ?? null,
relatedPosts: relatedPosts.data ?? null,
},
null,
4,
)}
</pre>
);
}

上記は、このデータを持つ正確に1つのHTTP呼び出しになります:

Locationプロパティ
pathname/api/trpc/postById,relatedPosts
search?batch=1&input=%7B%220%22%3A%221%22%2C%221%22%3A%221%22%7D *

*)上記のinputは、

ts
encodeURIComponent(
JSON.stringify({
0: '1', // <-- input for `postById`
1: '1', // <-- input for `relatedPosts`
}),
);
ts
encodeURIComponent(
JSON.stringify({
0: '1', // <-- input for `postById`
1: '1', // <-- input for `relatedPosts`
}),
);

バッチ処理の例:レスポンス

サーバーからの出力例
json
[
// result for `postById`
{
"result": {
"data": {
"id": "1",
"title": "Hello tRPC",
"body": "..."
// ...
}
}
},
// result for `relatedPosts`
{
"result": {
"data": [
/* ... */
]
}
}
]
json
[
// result for `postById`
{
"result": {
"data": {
"id": "1",
"title": "Hello tRPC",
"body": "..."
// ...
}
}
},
// result for `relatedPosts`
{
"result": {
"data": [
/* ... */
]
}
}
]

HTTPレスポンス仕様

トランスポートレイヤーに関係なく機能する仕様にするために、可能な限りJSON-RPC 2.0に準拠しようとします。

成功レスポンス

JSONレスポンスの例
json
{
"result": {
"data": {
"id": "1",
"title": "Hello tRPC",
"body": "..."
}
}
}
json
{
"result": {
"data": {
"id": "1",
"title": "Hello tRPC",
"body": "..."
}
}
}
ts
{
result: {
data: TOutput; // output from procedure
}
}
ts
{
result: {
data: TOutput; // output from procedure
}
}

エラーレスポンス

JSONレスポンスの例
json
[
{
"error": {
"json": {
"message": "Something went wrong",
"code": -32600, // JSON-RPC 2.0 code
"data": {
// Extra, customizable, meta data
"code": "INTERNAL_SERVER_ERROR",
"httpStatus": 500,
"stack": "...",
"path": "post.add"
}
}
}
}
]
json
[
{
"error": {
"json": {
"message": "Something went wrong",
"code": -32600, // JSON-RPC 2.0 code
"data": {
// Extra, customizable, meta data
"code": "INTERNAL_SERVER_ERROR",
"httpStatus": 500,
"stack": "...",
"path": "post.add"
}
}
}
}
]

  • 可能な限り、発生したエラーからHTTPステータスコードを伝播します。
  • レスポンスに異なるステータスがある場合、207 Multi-Statusを返します(例:1つの呼び出しがエラーになり、1つが成功した場合)。
  • エラーとそれらをカスタマイズする方法の詳細については、エラーフォーマットを参照してください。

エラーコード <-> HTTPステータス

ts
PARSE_ERROR: 400,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
NOT_FOUND: 404,
FORBIDDEN: 403,
METHOD_NOT_SUPPORTED: 405,
TIMEOUT: 408,
CONFLICT: 409,
PRECONDITION_FAILED: 412,
PAYLOAD_TOO_LARGE: 413,
UNPROCESSABLE_CONTENT: 422,
TOO_MANY_REQUESTS: 429,
CLIENT_CLOSED_REQUEST: 499,
INTERNAL_SERVER_ERROR: 500,
NOT_IMPLEMENTED: 501,
ts
PARSE_ERROR: 400,
BAD_REQUEST: 400,
UNAUTHORIZED: 401,
NOT_FOUND: 404,
FORBIDDEN: 403,
METHOD_NOT_SUPPORTED: 405,
TIMEOUT: 408,
CONFLICT: 409,
PRECONDITION_FAILED: 412,
PAYLOAD_TOO_LARGE: 413,
UNPROCESSABLE_CONTENT: 422,
TOO_MANY_REQUESTS: 429,
CLIENT_CLOSED_REQUEST: 499,
INTERNAL_SERVER_ERROR: 500,
NOT_IMPLEMENTED: 501,

エラーコード <-> JSON-RPC 2.0エラーコード

使用可能なコードとJSON-RPCコード
ts
/**
* JSON-RPC 2.0 Error codes
*
* `-32000` to `-32099` are reserved for implementation-defined server-errors.
* For tRPC we're copying the last digits of HTTP 4XX errors.
*/
export const TRPC_ERROR_CODES_BY_KEY = {
/**
* Invalid JSON was received by the server.
* An error occurred on the server while parsing the JSON text.
*/
PARSE_ERROR: -32700,
/**
* The JSON sent is not a valid Request object.
*/
BAD_REQUEST: -32600, // 400
// Internal JSON-RPC error
INTERNAL_SERVER_ERROR: -32603,
NOT_IMPLEMENTED: -32603,
// Implementation specific errors
UNAUTHORIZED: -32001, // 401
FORBIDDEN: -32003, // 403
NOT_FOUND: -32004, // 404
METHOD_NOT_SUPPORTED: -32005, // 405
TIMEOUT: -32008, // 408
CONFLICT: -32009, // 409
PRECONDITION_FAILED: -32012, // 412
PAYLOAD_TOO_LARGE: -32013, // 413
UNPROCESSABLE_CONTENT: -32022, // 422
TOO_MANY_REQUESTS: -32029, // 429
CLIENT_CLOSED_REQUEST: -32099, // 499
} as const;
ts
/**
* JSON-RPC 2.0 Error codes
*
* `-32000` to `-32099` are reserved for implementation-defined server-errors.
* For tRPC we're copying the last digits of HTTP 4XX errors.
*/
export const TRPC_ERROR_CODES_BY_KEY = {
/**
* Invalid JSON was received by the server.
* An error occurred on the server while parsing the JSON text.
*/
PARSE_ERROR: -32700,
/**
* The JSON sent is not a valid Request object.
*/
BAD_REQUEST: -32600, // 400
// Internal JSON-RPC error
INTERNAL_SERVER_ERROR: -32603,
NOT_IMPLEMENTED: -32603,
// Implementation specific errors
UNAUTHORIZED: -32001, // 401
FORBIDDEN: -32003, // 403
NOT_FOUND: -32004, // 404
METHOD_NOT_SUPPORTED: -32005, // 405
TIMEOUT: -32008, // 408
CONFLICT: -32009, // 409
PRECONDITION_FAILED: -32012, // 412
PAYLOAD_TOO_LARGE: -32013, // 413
UNPROCESSABLE_CONTENT: -32022, // 422
TOO_MANY_REQUESTS: -32029, // 429
CLIENT_CLOSED_REQUEST: -32099, // 499
} as const;

デフォルトのHTTPメソッドのオーバーライド

クエリ/ミューテーションに使用されるHTTPメソッドをオーバーライドするには、methodOverrideオプションを使用できます。

server/httpHandler.ts
tsx
// Your server must separately allow the client to override the HTTP method
const handler = createHTTPHandler({
router: router,
allowMethodOverride: true,
});
server/httpHandler.ts
tsx
// Your server must separately allow the client to override the HTTP method
const handler = createHTTPHandler({
router: router,
allowMethodOverride: true,
});
client/trpc.ts
tsx
// The client can then specify which HTTP method to use for all queries/mutations
const client = createTRPCClient<AppRouter>({
links: [
httpLink({
url: `http://localhost:3000`,
methodOverride: 'POST', // all queries and mutations will be sent to the tRPC Server as POST requests.
}),
],
});
client/trpc.ts
tsx
// The client can then specify which HTTP method to use for all queries/mutations
const client = createTRPCClient<AppRouter>({
links: [
httpLink({
url: `http://localhost:3000`,
methodOverride: 'POST', // all queries and mutations will be sent to the tRPC Server as POST requests.
}),
],
});

詳細

TypeScript定義を詳しく調べて、詳細を確認できます。