@orpc/server 2.0.0-beta.49 → 2.0.0-beta.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/aws-lambda/handler.d.ts +17 -15
- package/dist/adapters/aws-lambda/handler.js +23 -23
- package/dist/adapters/aws-lambda/index.d.ts +4 -16
- package/dist/adapters/aws-lambda/index.js +2 -2
- package/dist/adapters/aws-lambda/rpc-handler.d.ts +9 -9
- package/dist/adapters/aws-lambda/rpc-handler.js +20 -17
- package/dist/adapters/crossws/handler.d.ts +44 -42
- package/dist/adapters/crossws/handler.js +53 -60
- package/dist/adapters/crossws/index.d.ts +3 -2
- package/dist/adapters/crossws/index.js +2 -2
- package/dist/adapters/crossws/rpc-handler.d.ts +10 -10
- package/dist/adapters/crossws/rpc-handler.js +17 -14
- package/dist/adapters/fastify/handler.d.ts +17 -15
- package/dist/adapters/fastify/handler.js +20 -20
- package/dist/adapters/fastify/index.d.ts +3 -2
- package/dist/adapters/fastify/index.js +2 -2
- package/dist/adapters/fastify/rpc-handler.d.ts +9 -9
- package/dist/adapters/fastify/rpc-handler.js +16 -13
- package/dist/adapters/fetch/handler.d.ts +19 -17
- package/dist/adapters/fetch/handler.js +22 -22
- package/dist/adapters/fetch/index.d.ts +4 -7
- package/dist/adapters/fetch/index.js +3 -7
- package/dist/adapters/fetch/rpc-handler.d.ts +9 -9
- package/dist/adapters/fetch/rpc-handler.js +18 -15
- package/dist/adapters/message-port/handler.d.ts +58 -60
- package/dist/adapters/message-port/handler.js +72 -86
- package/dist/adapters/message-port/index.d.ts +3 -2
- package/dist/adapters/message-port/index.js +2 -2
- package/dist/adapters/message-port/rpc-handler.d.ts +9 -9
- package/dist/adapters/message-port/rpc-handler.js +17 -14
- package/dist/adapters/node/handler.d.ts +17 -15
- package/dist/adapters/node/handler.js +20 -20
- package/dist/adapters/node/index.d.ts +4 -7
- package/dist/adapters/node/index.js +3 -7
- package/dist/adapters/node/rpc-handler.d.ts +9 -9
- package/dist/adapters/node/rpc-handler.js +17 -14
- package/dist/adapters/standard/codec.d.ts +13 -13
- package/dist/adapters/standard/handler.d.ts +49 -49
- package/dist/adapters/standard/handler.js +205 -205
- package/dist/adapters/standard/index.d.ts +7 -6
- package/dist/adapters/standard/index.js +4 -5
- package/dist/adapters/standard/plugin.d.ts +25 -31
- package/dist/adapters/standard/plugin.js +14 -16
- package/dist/adapters/standard/rpc-handler-codec.d.ts +39 -43
- package/dist/adapters/standard/rpc-handler-codec.js +50 -51
- package/dist/adapters/standard/rpc-matcher.d.ts +40 -40
- package/dist/adapters/standard/rpc-matcher.js +103 -149
- package/dist/adapters/standard/utils.d.ts +8 -8
- package/dist/adapters/standard/utils.js +7 -5
- package/dist/adapters/standard-peer/index.d.ts +2 -1
- package/dist/adapters/standard-peer/index.js +1 -1
- package/dist/adapters/standard-peer/utils.d.ts +6 -4
- package/dist/adapters/standard-peer/utils.js +12 -6
- package/dist/adapters/websocket/handler.d.ts +52 -50
- package/dist/adapters/websocket/handler.js +75 -85
- package/dist/adapters/websocket/index.d.ts +3 -2
- package/dist/adapters/websocket/index.js +2 -2
- package/dist/adapters/websocket/rpc-handler.d.ts +9 -9
- package/dist/adapters/websocket/rpc-handler.js +17 -14
- package/dist/builder-variants.d.ts +195 -195
- package/dist/builder.d.ts +103 -104
- package/dist/builder.js +198 -224
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +4 -2
- package/dist/context.d.ts +3 -3
- package/dist/extensions/callable.d.ts +11 -11
- package/dist/extensions/callable.js +6 -5
- package/dist/helpers/base64url.d.ts +1 -1
- package/dist/helpers/base64url.js +44 -49
- package/dist/helpers/cookie.d.ts +10 -11
- package/dist/helpers/cookie.js +56 -63
- package/dist/helpers/encryption.d.ts +1 -1
- package/dist/helpers/encryption.js +80 -70
- package/dist/helpers/index.d.ts +5 -4
- package/dist/helpers/index.js +4 -4
- package/dist/helpers/signing.d.ts +1 -1
- package/dist/helpers/signing.js +72 -82
- package/dist/implementer-procedure.d.ts +12 -13
- package/dist/implementer-procedure.js +37 -44
- package/dist/implementer-router.d.ts +30 -36
- package/dist/implementer-router.js +92 -111
- package/dist/implementer.d.ts +8 -8
- package/dist/implementer.js +28 -35
- package/dist/index.d.ts +22 -61
- package/dist/index.js +16 -48
- package/dist/lazy.d.ts +14 -14
- package/dist/lazy.js +19 -30
- package/dist/middleware-decorated.d.ts +8 -9
- package/dist/middleware-decorated.js +66 -70
- package/dist/middleware.d.ts +34 -34
- package/dist/plugins/batch.d.ts +75 -75
- package/dist/plugins/batch.js +345 -379
- package/dist/plugins/cors.d.ts +60 -64
- package/dist/plugins/cors.js +118 -111
- package/dist/plugins/get-method-csrf-protection.d.ts +8 -6
- package/dist/plugins/get-method-csrf-protection.js +47 -63
- package/dist/plugins/head-method.d.ts +11 -9
- package/dist/plugins/head-method.js +97 -94
- package/dist/plugins/index.d.ts +15 -39
- package/dist/plugins/index.js +14 -29
- package/dist/plugins/method-override.d.ts +30 -28
- package/dist/plugins/method-override.js +53 -49
- package/dist/plugins/request-compression.d.ts +11 -9
- package/dist/plugins/request-compression.js +52 -79
- package/dist/plugins/request-headers.d.ts +10 -8
- package/dist/plugins/request-headers.js +27 -29
- package/dist/plugins/request-limit.d.ts +21 -19
- package/dist/plugins/request-limit.js +60 -67
- package/dist/plugins/response-compression.d.ts +42 -39
- package/dist/plugins/response-compression.js +150 -202
- package/dist/plugins/response-headers.d.ts +15 -13
- package/dist/plugins/response-headers.js +43 -46
- package/dist/plugins/rethrow.d.ts +25 -23
- package/dist/plugins/rethrow.js +46 -58
- package/dist/plugins/signal-sync.d.ts +7 -5
- package/dist/plugins/signal-sync.js +71 -86
- package/dist/plugins/timeout.d.ts +29 -27
- package/dist/plugins/timeout.js +61 -58
- package/dist/procedure-client.d.ts +14 -15
- package/dist/procedure-client.js +149 -166
- package/dist/procedure-decorated.d.ts +9 -9
- package/dist/procedure-decorated.js +36 -44
- package/dist/procedure-utils.d.ts +10 -30
- package/dist/procedure-utils.js +39 -40
- package/dist/procedure.d.ts +60 -60
- package/dist/procedure.js +18 -24
- package/dist/router-client.d.ts +9 -11
- package/dist/router-client.js +33 -41
- package/dist/router-hidden.js +10 -12
- package/dist/router-utils.d.ts +13 -30
- package/dist/router-utils.js +146 -191
- package/dist/router.d.ts +12 -26
- package/package.json +10 -10
- package/dist/adapters/standard/codec.js +0 -1
- package/dist/builder-variants.js +0 -1
- package/dist/context.js +0 -1
- package/dist/middleware.js +0 -1
- package/dist/router-hidden.d.ts +0 -5
- package/dist/router.js +0 -1
|
@@ -1,209 +1,157 @@
|
|
|
1
|
-
import { isAcceptableEncoding, isAsyncIteratorObject, isCompressibleContentType, isNoTransformCacheControl, parseAcceptEncodingQualities, toArray, varyByAcceptEncoding
|
|
2
|
-
import { flattenStandardHeader, generateContentDisposition } from
|
|
3
|
-
import { toFetchBody } from
|
|
4
|
-
//
|
|
5
|
-
// occasional multi-byte characters increase the average.
|
|
6
|
-
const AVG_BYTES_PER_CHAR = 1.2;
|
|
1
|
+
import { estimateCompressibleFormDataSize, estimateUtf8ByteLength, isAcceptableEncoding, isAsyncIteratorObject, isCompressibleContentType, isNoTransformCacheControl, parseAcceptEncodingQualities, toArray, varyByAcceptEncoding } from "@orpc/shared";
|
|
2
|
+
import { flattenStandardHeader, generateContentDisposition } from "@standard-server/core";
|
|
3
|
+
import { toFetchBody } from "@standard-server/fetch";
|
|
4
|
+
// src/plugins/response-compression.ts
|
|
7
5
|
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
else if (body instanceof URLSearchParams) {
|
|
121
|
-
const string = body.toString();
|
|
122
|
-
if (string.length * AVG_BYTES_PER_CHAR >= this.threshold) {
|
|
123
|
-
const [, bodyHeaders] = toFetchBody(body, headers);
|
|
124
|
-
return {
|
|
125
|
-
...result,
|
|
126
|
-
response: {
|
|
127
|
-
...response,
|
|
128
|
-
body: new Blob([string]).stream().pipeThrough(new CompressionStream(encoding)),
|
|
129
|
-
headers: {
|
|
130
|
-
...toCompressedHeaders(bodyHeaders, encoding),
|
|
131
|
-
// An empty hint rather than none, so the adapter does not hint the compressed stream as `octet-stream`
|
|
132
|
-
'standard-server': bodyHeaders['standard-server'] ?? [],
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else if (body !== undefined && !isAsyncIteratorObject(body)) {
|
|
139
|
-
const [string, bodyHeaders] = toFetchBody(body, headers);
|
|
140
|
-
if (string.length * AVG_BYTES_PER_CHAR >= this.threshold) {
|
|
141
|
-
return {
|
|
142
|
-
...result,
|
|
143
|
-
response: {
|
|
144
|
-
...response,
|
|
145
|
-
body: new Blob([string]).stream().pipeThrough(new CompressionStream(encoding)),
|
|
146
|
-
headers: {
|
|
147
|
-
...toCompressedHeaders(bodyHeaders, encoding),
|
|
148
|
-
'standard-server': bodyHeaders['standard-server'] ?? [],
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return result;
|
|
155
|
-
};
|
|
156
|
-
return {
|
|
157
|
-
...options,
|
|
158
|
-
routingInterceptors: [routingInterceptor, ...toArray(options.routingInterceptors)],
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
}
|
|
6
|
+
* Compresses response bodies based on the client's Accept-Encoding header.
|
|
7
|
+
* Works at the standard handler level, so it supports all adapters.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link https://orpc.dev/docs/plugins/response-compression | Response Compression Plugin}
|
|
10
|
+
*/
|
|
11
|
+
var ResponseCompressionHandlerPlugin = class {
|
|
12
|
+
name = "~response-compression";
|
|
13
|
+
/**
|
|
14
|
+
* Compression should be done after batching, to compress the final response.
|
|
15
|
+
* Compression should also be done after response headers are set, to access final headers like Content-Type and Cache-Control.
|
|
16
|
+
*/
|
|
17
|
+
after = ["~batch", "~response-headers"];
|
|
18
|
+
encodings;
|
|
19
|
+
threshold;
|
|
20
|
+
isCompressibleContentType;
|
|
21
|
+
constructor(options = {}) {
|
|
22
|
+
this.encodings = options.encodings ?? ["gzip", "deflate"];
|
|
23
|
+
this.threshold = options.threshold ?? 1024;
|
|
24
|
+
this.isCompressibleContentType = options.isCompressibleContentType ?? isCompressibleContentType;
|
|
25
|
+
}
|
|
26
|
+
init(options) {
|
|
27
|
+
const routingInterceptor = async ({ next, ...interceptorOptions }) => {
|
|
28
|
+
const result = await next();
|
|
29
|
+
if (!result.matched) return result;
|
|
30
|
+
const response = result.response;
|
|
31
|
+
const encoding = negotiateResponseCompressionEncoding(response, interceptorOptions.request.headers, this.encodings);
|
|
32
|
+
if (encoding === void 0) return result;
|
|
33
|
+
const body = response.body;
|
|
34
|
+
const headers = response.headers;
|
|
35
|
+
if (body instanceof ReadableStream) {
|
|
36
|
+
const contentLength = Number(flattenStandardHeader(headers["content-length"]));
|
|
37
|
+
if ((!Number.isFinite(contentLength) || contentLength >= this.threshold) && this.isCompressibleContentType(flattenStandardHeader(headers["content-type"]), interceptorOptions)) return {
|
|
38
|
+
...result,
|
|
39
|
+
response: {
|
|
40
|
+
...response,
|
|
41
|
+
body: body.pipeThrough(new CompressionStream(encoding)),
|
|
42
|
+
headers: toCompressedHeaders(headers, encoding)
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
} else if (body instanceof Blob) {
|
|
46
|
+
const contentType = headers["content-type"] ?? body.type;
|
|
47
|
+
if ((!Number.isFinite(body.size) || body.size >= this.threshold) && this.isCompressibleContentType(flattenStandardHeader(contentType), interceptorOptions)) {
|
|
48
|
+
const contentDisposition = headers["content-disposition"] ?? generateContentDisposition(body instanceof File ? body.name : "blob");
|
|
49
|
+
return {
|
|
50
|
+
...result,
|
|
51
|
+
response: {
|
|
52
|
+
...response,
|
|
53
|
+
body: body.stream().pipeThrough(new CompressionStream(encoding)),
|
|
54
|
+
headers: {
|
|
55
|
+
...toCompressedHeaders(headers, encoding),
|
|
56
|
+
"standard-server": headers["standard-server"] ?? "file",
|
|
57
|
+
"content-type": contentType,
|
|
58
|
+
"content-disposition": contentDisposition
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
} else if (body instanceof FormData) {
|
|
64
|
+
if (estimateCompressibleFormDataSize(body, (contentType) => this.isCompressibleContentType(contentType, interceptorOptions)) >= this.threshold) {
|
|
65
|
+
const res = new Response(body);
|
|
66
|
+
const compressedStream = res.body.pipeThrough(new CompressionStream(encoding));
|
|
67
|
+
return {
|
|
68
|
+
...result,
|
|
69
|
+
response: {
|
|
70
|
+
...response,
|
|
71
|
+
body: compressedStream,
|
|
72
|
+
headers: {
|
|
73
|
+
...toCompressedHeaders(headers, encoding),
|
|
74
|
+
"standard-server": [],
|
|
75
|
+
"content-type": res.headers.get("content-type")
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
} else if (body instanceof URLSearchParams) {
|
|
81
|
+
const string = body.toString();
|
|
82
|
+
if (estimateUtf8ByteLength(string) >= this.threshold) {
|
|
83
|
+
const [, bodyHeaders] = toFetchBody(body, headers);
|
|
84
|
+
return {
|
|
85
|
+
...result,
|
|
86
|
+
response: {
|
|
87
|
+
...response,
|
|
88
|
+
body: new Blob([string]).stream().pipeThrough(new CompressionStream(encoding)),
|
|
89
|
+
headers: {
|
|
90
|
+
...toCompressedHeaders(bodyHeaders, encoding),
|
|
91
|
+
"standard-server": bodyHeaders["standard-server"] ?? []
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
} else if (body !== void 0 && !isAsyncIteratorObject(body)) {
|
|
97
|
+
const [string, bodyHeaders] = toFetchBody(body, headers);
|
|
98
|
+
if (estimateUtf8ByteLength(string) >= this.threshold) return {
|
|
99
|
+
...result,
|
|
100
|
+
response: {
|
|
101
|
+
...response,
|
|
102
|
+
body: new Blob([string]).stream().pipeThrough(new CompressionStream(encoding)),
|
|
103
|
+
headers: {
|
|
104
|
+
...toCompressedHeaders(bodyHeaders, encoding),
|
|
105
|
+
"standard-server": bodyHeaders["standard-server"] ?? []
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
...options,
|
|
114
|
+
routingInterceptors: [routingInterceptor, ...toArray(options.routingInterceptors)]
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
};
|
|
162
118
|
/**
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
flattenStandardHeader(response.headers['content-range']) !== undefined) {
|
|
178
|
-
return undefined;
|
|
179
|
-
}
|
|
180
|
-
// Cache-Control: no-transform forbids intermediaries (and these plugins) from transforming the body
|
|
181
|
-
if (isNoTransformCacheControl(flattenStandardHeader(response.headers['cache-control']))) {
|
|
182
|
-
return undefined;
|
|
183
|
-
}
|
|
184
|
-
const acceptEncodings = parseAcceptEncodingQualities(flattenStandardHeader(requestHeaders['accept-encoding']));
|
|
185
|
-
return encodings.find((encoding) => isAcceptableEncoding(acceptEncodings, encoding));
|
|
119
|
+
* Picks the first of `encodings` the client accepts, or `undefined` when the response
|
|
120
|
+
* must be sent as is because it is already encoded, partial, or forbids transforms.
|
|
121
|
+
* Shared by the response compression plugins so they agree on when to compress.
|
|
122
|
+
*/
|
|
123
|
+
function negotiateResponseCompressionEncoding(response, requestHeaders, encodings) {
|
|
124
|
+
if (flattenStandardHeader(response.headers["content-encoding"]) !== void 0) return;
|
|
125
|
+
/**
|
|
126
|
+
* A partial response body is a byte range of the identity representation, so compressing it
|
|
127
|
+
* would leave `Content-Range` describing offsets the client never receives.
|
|
128
|
+
*/
|
|
129
|
+
if (response.status === 206 || flattenStandardHeader(response.headers["content-range"]) !== void 0) return;
|
|
130
|
+
if (isNoTransformCacheControl(flattenStandardHeader(response.headers["cache-control"]))) return;
|
|
131
|
+
const acceptEncodings = parseAcceptEncodingQualities(flattenStandardHeader(requestHeaders["accept-encoding"]));
|
|
132
|
+
return encodings.find((encoding) => isAcceptableEncoding(acceptEncodings, encoding));
|
|
186
133
|
}
|
|
187
134
|
/**
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
135
|
+
* The headers of a response whose body is compressed with `encoding`.
|
|
136
|
+
* Shared by the response compression plugins so compressed responses carry the same headers.
|
|
137
|
+
*/
|
|
138
|
+
function toCompressedHeaders(headers, encoding) {
|
|
139
|
+
return {
|
|
140
|
+
...headers,
|
|
141
|
+
"content-length": [],
|
|
142
|
+
"content-encoding": encoding,
|
|
143
|
+
"vary": varyByAcceptEncoding(flattenStandardHeader(headers.vary)),
|
|
144
|
+
/**
|
|
145
|
+
* A strong tag shared with the identity bytes would let `If-Range` splice them after compressed ones.
|
|
146
|
+
* A weak tag still revalidates through `If-None-Match`, and the compressed body serves no ranges.
|
|
147
|
+
*
|
|
148
|
+
* @see https://www.rfc-editor.org/rfc/rfc9110.html#name-etag
|
|
149
|
+
*/
|
|
150
|
+
"etag": weakenEtag(flattenStandardHeader(headers.etag)),
|
|
151
|
+
"accept-ranges": []
|
|
152
|
+
};
|
|
206
153
|
}
|
|
207
154
|
function weakenEtag(etag) {
|
|
208
|
-
|
|
155
|
+
return etag === void 0 || etag.startsWith("W/") ? etag : `W/${etag}`;
|
|
209
156
|
}
|
|
157
|
+
export { ResponseCompressionHandlerPlugin, negotiateResponseCompressionEncoding, toCompressedHeaders };
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { StandardHandlerPlugin } from "../adapters/standard/plugin.js";
|
|
2
|
+
import { StandardHandlerOptions } from "../adapters/standard/handler.js";
|
|
3
|
+
import "../adapters/standard/index.js";
|
|
2
4
|
/**
|
|
3
5
|
* The context shape into which the Response Headers Plugin injects `resHeaders`.
|
|
4
6
|
*
|
|
5
7
|
* @see {@link https://orpc.dev/docs/plugins/response-headers | Response Headers Plugin}
|
|
6
8
|
*/
|
|
7
9
|
export interface ResponseHeadersHandlerPluginContext {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Response headers as a Headers instance. This is injected by the Response Headers Plugin.
|
|
12
|
+
* When set before the response is sent, these headers will be included in the response. If not set, no additional headers will be added.
|
|
13
|
+
*/
|
|
14
|
+
resHeaders?: Headers | undefined;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* The Response Headers Plugin allows you to set response headers in oRPC.
|
|
@@ -21,10 +23,10 @@ export interface ResponseHeadersHandlerPluginContext {
|
|
|
21
23
|
* @see {@link https://orpc.dev/docs/plugins/response-headers | Response Headers Plugin}
|
|
22
24
|
*/
|
|
23
25
|
export declare class ResponseHeadersHandlerPlugin<T extends ResponseHeadersHandlerPluginContext> implements StandardHandlerPlugin<T> {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
26
|
+
name: string;
|
|
27
|
+
/**
|
|
28
|
+
* Interceptors should run after batch interceptors so headers are applied to each sub-response.
|
|
29
|
+
*/
|
|
30
|
+
before: string[];
|
|
31
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
32
|
+
}
|
|
@@ -1,47 +1,44 @@
|
|
|
1
|
-
import { toArray } from
|
|
2
|
-
import { mergeStandardHeaders } from
|
|
3
|
-
import { toStandardHeaders } from
|
|
1
|
+
import { toArray } from "@orpc/shared";
|
|
2
|
+
import { mergeStandardHeaders } from "@standard-server/core";
|
|
3
|
+
import { toStandardHeaders } from "@standard-server/fetch";
|
|
4
|
+
// src/plugins/response-headers.ts
|
|
4
5
|
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
],
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
}
|
|
6
|
+
* The Response Headers Plugin allows you to set response headers in oRPC.
|
|
7
|
+
* It injects a resHeaders instance into the context, enabling you to modify response headers easily.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* **Warning**: In a `streaming` batch, only the cookies of the first procedure to respond reach the client.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link https://orpc.dev/docs/plugins/response-headers | Response Headers Plugin}
|
|
13
|
+
*/
|
|
14
|
+
var ResponseHeadersHandlerPlugin = class {
|
|
15
|
+
name = "~response-headers";
|
|
16
|
+
/**
|
|
17
|
+
* Interceptors should run after batch interceptors so headers are applied to each sub-response.
|
|
18
|
+
*/
|
|
19
|
+
before = ["~batch"];
|
|
20
|
+
init(options) {
|
|
21
|
+
return {
|
|
22
|
+
...options,
|
|
23
|
+
routingInterceptors: [async (interceptorOptions) => {
|
|
24
|
+
const resHeaders = new Headers(interceptorOptions.context.resHeaders);
|
|
25
|
+
const result = await interceptorOptions.next({
|
|
26
|
+
...interceptorOptions,
|
|
27
|
+
context: {
|
|
28
|
+
...interceptorOptions.context,
|
|
29
|
+
resHeaders
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (!result.response) return result;
|
|
33
|
+
return {
|
|
34
|
+
...result,
|
|
35
|
+
response: {
|
|
36
|
+
...result.response,
|
|
37
|
+
headers: mergeStandardHeaders(result.response.headers, toStandardHeaders(resHeaders))
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}, ...toArray(options.routingInterceptors)]
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
export { ResponseHeadersHandlerPlugin };
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import "../adapters/standard/index.js";
|
|
2
|
+
import { StandardHandlerPlugin } from "../adapters/standard/plugin.js";
|
|
3
|
+
import { StandardHandlerInterceptorOptions, StandardHandlerOptions } from "../adapters/standard/handler.js";
|
|
4
|
+
import { Context } from "../context.js";
|
|
5
|
+
import { ThrowableError } from "@orpc/shared";
|
|
4
6
|
export interface RethrowHandlerPluginOptions<T extends Context> {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Decide which errors should be rethrown.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const rethrowPlugin = new RethrowHandlerPlugin({
|
|
13
|
+
* filter: (error) => {
|
|
14
|
+
* // Rethrow all non-ORPCError errors
|
|
15
|
+
* return !(error instanceof ORPCError)
|
|
16
|
+
* }
|
|
17
|
+
* })
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
filter: (error: ThrowableError, options: StandardHandlerInterceptorOptions<T>) => boolean;
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
23
|
* The plugin can bypass oRPC's built-in error handling
|
|
@@ -25,9 +27,9 @@ export interface RethrowHandlerPluginOptions<T extends Context> {
|
|
|
25
27
|
* @see {@link https://orpc.dev/docs/plugins/rethrow | Rethrow Handler Plugin}
|
|
26
28
|
*/
|
|
27
29
|
export declare class RethrowHandlerPlugin<T extends Context> implements StandardHandlerPlugin<T> {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
30
|
+
name: string;
|
|
31
|
+
private readonly filter;
|
|
32
|
+
private readonly CONTEXT_SYMBOL;
|
|
33
|
+
constructor(options: RethrowHandlerPluginOptions<T>);
|
|
34
|
+
init(options: StandardHandlerOptions<T>): StandardHandlerOptions<T>;
|
|
35
|
+
}
|