0
# HTTP Transport Links
1
2
HTTP-based transport mechanisms including standard HTTP, batching, and streaming capabilities for queries and mutations. These links handle communication with tRPC servers over HTTP protocols.
3
4
## Capabilities
5
6
### httpLink
7
8
Standard HTTP transport for individual queries and mutations. Each operation results in a separate HTTP request.
9
10
```typescript { .api }
11
/**
12
* Creates an HTTP transport link for individual requests
13
* @param opts - HTTP link configuration options
14
* @returns HTTP transport link for the client chain
15
*/
16
function httpLink<TRouter extends AnyRouter>(
17
opts: HTTPLinkOptions<TRouter['_def']['_config']['$types']>
18
): TRPCLink<TRouter>;
19
20
interface HTTPLinkOptions<TRoot extends AnyClientTypes> {
21
/** Server endpoint URL */
22
url: string | URL;
23
24
/** Static headers or function returning headers */
25
headers?: HTTPHeaders | ((opts: { op: Operation }) => HTTPHeaders | Promise<HTTPHeaders>);
26
27
/** Data transformation configuration */
28
transformer?: TRoot['transformer'];
29
30
/** Custom fetch implementation */
31
fetch?: FetchEsque;
32
33
/** Send all requests as POST regardless of procedure type */
34
methodOverride?: 'POST';
35
}
36
37
type HTTPHeaders = Record<string, string | string[]> | Headers;
38
```
39
40
**Usage Examples:**
41
42
```typescript
43
import { createTRPCClient, httpLink } from "@trpc/client";
44
45
// Basic HTTP link
46
const client = createTRPCClient<AppRouter>({
47
links: [
48
httpLink({
49
url: "http://localhost:3000/trpc",
50
}),
51
],
52
});
53
54
// HTTP link with authentication headers
55
const client = createTRPCClient<AppRouter>({
56
links: [
57
httpLink({
58
url: "http://localhost:3000/trpc",
59
headers: {
60
authorization: "Bearer " + getToken(),
61
},
62
}),
63
],
64
});
65
66
// Dynamic headers based on operation
67
const client = createTRPCClient<AppRouter>({
68
links: [
69
httpLink({
70
url: "http://localhost:3000/trpc",
71
headers: async ({ op }) => {
72
return {
73
authorization: await getAuthToken(),
74
"x-request-type": op.type,
75
"x-procedure-path": op.path,
76
};
77
},
78
}),
79
],
80
});
81
82
// Custom fetch implementation (Node.js)
83
const client = createTRPCClient<AppRouter>({
84
links: [
85
httpLink({
86
url: "http://localhost:3000/trpc",
87
fetch: fetch, // Node.js fetch polyfill
88
}),
89
],
90
});
91
```
92
93
### httpBatchLink
94
95
Batches multiple requests into single HTTP calls to reduce network overhead. Automatically groups operations and sends them together when possible.
96
97
```typescript { .api }
98
/**
99
* Creates an HTTP transport link that batches multiple requests
100
* @param opts - HTTP batch link configuration options
101
* @returns HTTP batch transport link for the client chain
102
*/
103
function httpBatchLink<TRouter extends AnyRouter>(
104
opts: HTTPBatchLinkOptions<TRouter['_def']['_config']['$types']>
105
): TRPCLink<TRouter>;
106
107
interface HTTPBatchLinkOptions<TRoot extends AnyClientTypes> {
108
/** Server endpoint URL */
109
url: string | URL;
110
111
/** Maximum URL length for batched requests */
112
maxURLLength?: number;
113
114
/** Maximum number of operations per batch */
115
maxItems?: number;
116
117
/** Static headers or batch-aware function returning headers */
118
headers?: HTTPHeaders | ((opts: { opList: NonEmptyArray<Operation> }) => HTTPHeaders | Promise<HTTPHeaders>);
119
120
/** Data transformation configuration */
121
transformer?: TRoot['transformer'];
122
123
/** Custom fetch implementation */
124
fetch?: FetchEsque;
125
126
/** Send all requests as POST regardless of procedure type */
127
methodOverride?: 'POST';
128
}
129
130
type NonEmptyArray<T> = [T, ...T[]];
131
```
132
133
**Usage Examples:**
134
135
```typescript
136
import { createTRPCClient, httpBatchLink } from "@trpc/client";
137
138
// Basic batch link
139
const client = createTRPCClient<AppRouter>({
140
links: [
141
httpBatchLink({
142
url: "http://localhost:3000/trpc",
143
}),
144
],
145
});
146
147
// Batch link with size limits
148
const client = createTRPCClient<AppRouter>({
149
links: [
150
httpBatchLink({
151
url: "http://localhost:3000/trpc",
152
maxURLLength: 2048, // Limit URL size
153
maxItems: 10, // Limit batch size
154
}),
155
],
156
});
157
158
// Batch-aware headers
159
const client = createTRPCClient<AppRouter>({
160
links: [
161
httpBatchLink({
162
url: "http://localhost:3000/trpc",
163
headers: ({ opList }) => ({
164
authorization: "Bearer " + getToken(),
165
"x-batch-size": opList.length.toString(),
166
"x-batch-operations": opList.map(op => op.path).join(","),
167
}),
168
}),
169
],
170
});
171
172
// Using the batched client (automatically batches concurrent calls)
173
const [user, posts, comments] = await Promise.all([
174
client.user.getById.query({ id: 1 }),
175
client.posts.getByUserId.query({ userId: 1 }),
176
client.comments.getByUserId.query({ userId: 1 }),
177
]);
178
```
179
180
### httpBatchStreamLink
181
182
Streaming batch transport using JSONL (JSON Lines) format for handling large batched responses efficiently.
183
184
```typescript { .api }
185
/**
186
* Creates a streaming HTTP batch link that handles responses as JSONL
187
* @param opts - HTTP batch stream link configuration options
188
* @returns Streaming HTTP batch transport link
189
*/
190
function httpBatchStreamLink<TRouter extends AnyRouter>(
191
opts: HTTPBatchStreamLinkOptions<TRouter['_def']['_config']['$types']>
192
): TRPCLink<TRouter>;
193
194
interface HTTPBatchStreamLinkOptions<TRoot extends AnyClientTypes> extends HTTPBatchLinkOptions<TRoot> {
195
/** Additional streaming configuration options */
196
}
197
```
198
199
**Usage Examples:**
200
201
```typescript
202
import { createTRPCClient, httpBatchStreamLink } from "@trpc/client";
203
204
// Streaming batch link for large responses
205
const client = createTRPCClient<AppRouter>({
206
links: [
207
httpBatchStreamLink({
208
url: "http://localhost:3000/trpc",
209
maxItems: 50, // Handle larger batches with streaming
210
}),
211
],
212
});
213
214
// Efficient for operations returning large datasets
215
const results = await Promise.all([
216
client.analytics.getUserMetrics.query({ range: "30d" }),
217
client.analytics.getPostMetrics.query({ range: "30d" }),
218
client.analytics.getEngagementData.query({ range: "30d" }),
219
]);
220
```
221
222
### httpSubscriptionLink
223
224
HTTP-based subscriptions using Server-Sent Events (SSE) for real-time communication without WebSocket connections.
225
226
```typescript { .api }
227
/**
228
* Creates an HTTP subscription link using Server-Sent Events
229
* @param opts - HTTP subscription link configuration options
230
* @returns HTTP subscription transport link
231
*/
232
function httpSubscriptionLink<TRouter extends AnyRouter>(
233
opts: HTTPSubscriptionLinkOptions<TRouter['_def']['_config']['$types']>
234
): TRPCLink<TRouter>;
235
236
interface HTTPSubscriptionLinkOptions<TRoot extends AnyClientTypes> extends HTTPLinkOptions<TRoot> {
237
/** Additional SSE-specific configuration */
238
}
239
```
240
241
**Usage Examples:**
242
243
```typescript
244
import { createTRPCClient, httpBatchLink, httpSubscriptionLink, splitLink } from "@trpc/client";
245
246
// Combined HTTP links for queries/mutations and subscriptions
247
const client = createTRPCClient<AppRouter>({
248
links: [
249
splitLink({
250
condition: (op) => op.type === 'subscription',
251
true: httpSubscriptionLink({
252
url: "http://localhost:3000/trpc",
253
}),
254
false: httpBatchLink({
255
url: "http://localhost:3000/trpc",
256
}),
257
}),
258
],
259
});
260
261
// Subscribe using HTTP SSE
262
const unsubscribe = client.posts.onUpdate.subscribe(undefined, {
263
onData: (post) => console.log("Post updated:", post),
264
onError: (err) => console.error("SSE error:", err),
265
});
266
```
267
268
### Content Type Support
269
270
HTTP links automatically detect and handle different content types for mutation inputs.
271
272
```typescript { .api }
273
/** Detect if value is FormData for file uploads */
274
function isFormData(value: unknown): boolean;
275
276
/** Detect if value is binary octet stream data */
277
function isOctetType(value: unknown): boolean;
278
279
/** Detect if value requires non-JSON serialization */
280
function isNonJsonSerializable(value: unknown): boolean;
281
```
282
283
**Content Type Examples:**
284
285
```typescript
286
// JSON payload (default)
287
await client.posts.create.mutate({
288
title: "Hello World",
289
content: "This is a post",
290
});
291
292
// FormData for file uploads
293
const formData = new FormData();
294
formData.append("file", fileInput.files[0]);
295
formData.append("title", "Image Upload");
296
297
await client.media.upload.mutate(formData);
298
299
// Binary octet stream
300
const binaryData = new Uint8Array([1, 2, 3, 4]);
301
await client.files.uploadBinary.mutate(binaryData);
302
303
// Automatically detects content type and sets appropriate headers
304
```
305
306
### Error Handling
307
308
HTTP links provide detailed error information including response metadata.
309
310
```typescript { .api }
311
interface HTTPResult {
312
/** HTTP response metadata */
313
meta: {
314
response: Response;
315
responseJSON?: any;
316
};
317
/** Parsed response data */
318
json: any;
319
}
320
```
321
322
**Error Handling Examples:**
323
324
```typescript
325
try {
326
const result = await client.user.getById.query({ id: 999 });
327
} catch (error) {
328
if (error instanceof TRPCClientError) {
329
// Access HTTP response details
330
const response = error.meta?.response;
331
const status = response?.status;
332
333
if (status === 404) {
334
console.log("User not found");
335
} else if (status === 401) {
336
redirectToLogin();
337
}
338
339
// Structured error data from server
340
console.log("Error code:", error.data?.code);
341
console.log("Error details:", error.data?.details);
342
}
343
}
344
```
345
346
### Configuration Options
347
348
Advanced configuration options for HTTP transport behavior.
349
350
```typescript { .api }
351
/** Custom fetch function interface */
352
type FetchEsque = (input: RequestInfo, init?: RequestInit) => Promise<Response>;
353
354
/** Base HTTP link configuration shared across HTTP transports */
355
interface HTTPLinkBaseOptions<TRoot extends AnyClientTypes> {
356
/** Server endpoint URL */
357
url: string | URL;
358
359
/** Custom fetch implementation */
360
fetch?: FetchEsque;
361
362
/** Force all requests to use POST method */
363
methodOverride?: 'POST';
364
365
/** Data transformation configuration */
366
transformer?: TransformerOptions<TRoot>;
367
}
368
369
/** Data transformation options */
370
interface TransformerOptions<TRoot> {
371
transformer?: TRoot['transformer'];
372
}
373
```
374
375
**Advanced Configuration Examples:**
376
377
```typescript
378
import { createTRPCClient, httpBatchLink } from "@trpc/client";
379
import fetch from "node-fetch";
380
381
// Node.js environment with custom fetch
382
const client = createTRPCClient<AppRouter>({
383
links: [
384
httpBatchLink({
385
url: "http://localhost:3000/trpc",
386
fetch: fetch as any,
387
methodOverride: "POST", // Force all requests to POST
388
}),
389
],
390
});
391
392
// Custom transformer (superjson example)
393
import superjson from "superjson";
394
395
const client = createTRPCClient<AppRouter>({
396
links: [
397
httpBatchLink({
398
url: "http://localhost:3000/trpc",
399
transformer: superjson,
400
}),
401
],
402
});
403
```