@entity-access/server-pages 1.0.43 → 1.1.3
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/Page.d.ts +6 -13
- package/dist/Page.d.ts.map +1 -1
- package/dist/Page.js +10 -44
- package/dist/Page.js.map +1 -1
- package/dist/ServerPages.d.ts.map +1 -1
- package/dist/ServerPages.js +14 -2
- package/dist/ServerPages.js.map +1 -1
- package/dist/core/CacheProperty.d.ts +5 -0
- package/dist/core/CacheProperty.d.ts.map +1 -0
- package/dist/core/CacheProperty.js +19 -0
- package/dist/core/CacheProperty.js.map +1 -0
- package/dist/core/Executor.d.ts +5 -0
- package/dist/core/Executor.d.ts.map +1 -0
- package/dist/core/Executor.js +13 -0
- package/dist/core/Executor.js.map +1 -0
- package/dist/core/RouteTree.d.ts.map +1 -1
- package/dist/core/RouteTree.js +15 -6
- package/dist/core/RouteTree.js.map +1 -1
- package/dist/core/SessionUser.d.ts +7 -5
- package/dist/core/SessionUser.d.ts.map +1 -1
- package/dist/core/SessionUser.js +36 -0
- package/dist/core/SessionUser.js.map +1 -1
- package/dist/core/Wrapped.d.ts +14 -16
- package/dist/core/Wrapped.d.ts.map +1 -1
- package/dist/core/Wrapped.js +157 -234
- package/dist/core/Wrapped.js.map +1 -1
- package/dist/decorators/Prepare.d.ts +14 -0
- package/dist/decorators/Prepare.d.ts.map +1 -0
- package/dist/decorators/Prepare.js +111 -0
- package/dist/decorators/Prepare.js.map +1 -0
- package/dist/routes/api/entity/index.d.ts.map +1 -1
- package/dist/routes/api/entity/index.js +9 -3
- package/dist/routes/api/entity/index.js.map +1 -1
- package/dist/routes/api/entity/model/get.d.ts.map +1 -1
- package/dist/routes/api/entity/model/get.js.map +1 -1
- package/dist/routes/api/entity/query/get.d.ts.map +1 -1
- package/dist/routes/api/entity/query/get.js +9 -3
- package/dist/routes/api/entity/query/get.js.map +1 -1
- package/dist/services/CookieService.d.ts.map +1 -1
- package/dist/services/CookieService.js +8 -0
- package/dist/services/CookieService.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Page.tsx +11 -53
- package/src/ServerPages.ts +14 -2
- package/src/core/CacheProperty.ts +18 -0
- package/src/core/Executor.ts +16 -0
- package/src/core/RouteTree.ts +7 -2
- package/src/core/SessionUser.ts +21 -5
- package/src/core/Wrapped.ts +215 -269
- package/src/decorators/Prepare.ts +132 -0
- package/src/routes/api/entity/index.tsx +4 -1
- package/src/routes/api/entity/model/get.tsx +1 -1
- package/src/routes/api/entity/query/get.ts +4 -1
- package/src/services/CookieService.ts +9 -1
- package/dist/decorators/Authorize.d.ts +0 -2
- package/dist/decorators/Authorize.d.ts.map +0 -1
- package/dist/decorators/Authorize.js +0 -3
- package/dist/decorators/Authorize.js.map +0 -1
- package/src/decorators/Authorize.ts +0 -3
package/src/core/Wrapped.ts
CHANGED
|
@@ -10,28 +10,39 @@ import { ServiceProvider } from "@entity-access/entity-access/dist/di/di.js";
|
|
|
10
10
|
import CookieService from "../services/CookieService.js";
|
|
11
11
|
import { stat } from "fs/promises";
|
|
12
12
|
import TokenService from "../services/TokenService.js";
|
|
13
|
+
import { CacheProperty } from "./CacheProperty.js";
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
type UnwrappedRequest = IncomingMessage | Http2ServerRequest;
|
|
16
17
|
|
|
18
|
+
type UnwrappedResponse = ServerResponse | Http2ServerResponse;
|
|
19
|
+
|
|
17
20
|
export interface IFormData {
|
|
18
21
|
fields: { [key: string]: string};
|
|
19
22
|
files: LocalFile[];
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
const extendedSymbol = Symbol("extended");
|
|
26
|
+
|
|
22
27
|
export interface IWrappedRequest {
|
|
23
28
|
|
|
29
|
+
headers?: any;
|
|
30
|
+
|
|
31
|
+
disposables?: Disposable[];
|
|
32
|
+
|
|
33
|
+
response?: WrappedResponse;
|
|
34
|
+
|
|
24
35
|
get host(): string;
|
|
25
36
|
|
|
26
37
|
get path(): string;
|
|
27
38
|
|
|
28
|
-
get
|
|
39
|
+
get sessionUser(): SessionUser;
|
|
29
40
|
|
|
30
|
-
get
|
|
41
|
+
get body(): any;
|
|
31
42
|
|
|
32
|
-
get
|
|
43
|
+
get form(): IFormData;
|
|
33
44
|
|
|
34
|
-
get
|
|
45
|
+
get params(): any;
|
|
35
46
|
|
|
36
47
|
get query(): { [key: string]: string};
|
|
37
48
|
|
|
@@ -45,12 +56,17 @@ export interface IWrappedRequest {
|
|
|
45
56
|
accepts(... types: string[]): boolean;
|
|
46
57
|
}
|
|
47
58
|
|
|
59
|
+
|
|
48
60
|
export interface IWrappedResponse {
|
|
49
61
|
|
|
62
|
+
request?: WrappedRequest;
|
|
63
|
+
|
|
50
64
|
asyncEnd();
|
|
51
65
|
|
|
52
66
|
asyncWrite(buffer: Buffer): Promise<void>;
|
|
53
67
|
|
|
68
|
+
setHeader(name: string, value: string);
|
|
69
|
+
|
|
54
70
|
send(data: Buffer | string | Blob, status?: number): Promise<void>;
|
|
55
71
|
|
|
56
72
|
sendRedirect(url: string, permanent?: boolean): void;
|
|
@@ -70,305 +86,235 @@ export interface IWrappedResponse {
|
|
|
70
86
|
|
|
71
87
|
}
|
|
72
88
|
|
|
73
|
-
export type WrappedRequest =
|
|
74
|
-
scope: ServiceProvider;
|
|
75
|
-
response: WrappedResponse;
|
|
76
|
-
disposables: Disposable[];
|
|
77
|
-
};
|
|
89
|
+
export type WrappedRequest = IWrappedRequest & UnwrappedRequest;
|
|
78
90
|
|
|
79
|
-
type
|
|
91
|
+
export type WrappedResponse = IWrappedResponse & UnwrappedResponse;
|
|
80
92
|
|
|
81
|
-
|
|
82
|
-
request: WrappedRequest
|
|
83
|
-
};
|
|
93
|
+
const extendRequest = (A: typeof IncomingMessage | typeof Http2ServerRequest) => {
|
|
84
94
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
},
|
|
95
|
+
let c = A[extendedSymbol];
|
|
96
|
+
if (!c) {
|
|
97
|
+
c = class IntermediateRequest extends A implements IWrappedRequest{
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return (...types: string[]) => {
|
|
93
|
-
if (types.length > 0) {
|
|
94
|
-
for (const type of types) {
|
|
95
|
-
for (const iterator of accepts) {
|
|
96
|
-
if (iterator.includes(type)) {
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
return accepts;
|
|
104
|
-
};
|
|
105
|
-
},
|
|
99
|
+
scope: ServiceProvider;
|
|
100
|
+
disposables: Disposable[];
|
|
106
101
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const cookies = parse(cookie);
|
|
130
|
-
return cookies;
|
|
131
|
-
},
|
|
102
|
+
get host(): string {
|
|
103
|
+
const r = this as any as (Http2ServerRequest | IncomingMessage);
|
|
104
|
+
const host = (r as Http2ServerRequest).authority || r.headers[":authority"] || r.headers.host || null;
|
|
105
|
+
return CacheProperty.value(this, "host", host);
|
|
106
|
+
}
|
|
107
|
+
get path(): string {
|
|
108
|
+
return this.URL.pathname;
|
|
109
|
+
}
|
|
110
|
+
get cookies(): { [key: string]: string; } {
|
|
111
|
+
const cookie = (this as any as UnwrappedRequest).headers.cookie;
|
|
112
|
+
const cookies = parse(cookie);
|
|
113
|
+
return CacheProperty.value(this, "cookies", cookies);
|
|
114
|
+
}
|
|
115
|
+
get URL(): URL {
|
|
116
|
+
const r = this as any as (Http2ServerRequest | IncomingMessage);
|
|
117
|
+
const url = new URL(r.url, `https:${this.host}`);
|
|
118
|
+
return CacheProperty.value(this, "URL", url);
|
|
119
|
+
}
|
|
120
|
+
get remoteIPAddress(): string {
|
|
121
|
+
const r = this as any as (Http2ServerRequest | IncomingMessage);
|
|
122
|
+
return CacheProperty.value(this, "remoteIPAddress", r.socket.remoteAddress);
|
|
123
|
+
}
|
|
132
124
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
125
|
+
accepts(... types: string[]): any {
|
|
126
|
+
const h = this as any as IncomingMessage;
|
|
127
|
+
const accepts = (h.headers.accept ?? "").split(";");
|
|
128
|
+
const value = (...types: string[]) => {
|
|
129
|
+
if (types.length > 0) {
|
|
130
|
+
for (const type of types) {
|
|
131
|
+
for (const iterator of accepts) {
|
|
132
|
+
if (iterator.includes(type)) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return accepts;
|
|
140
|
+
};
|
|
140
141
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!/\/json/i.test(contentType)) {
|
|
147
|
-
return {};
|
|
148
|
-
}
|
|
149
|
-
await new Promise<void>((resolve, reject) => {
|
|
150
|
-
req.pipe(new Writable({
|
|
151
|
-
write(chunk, enc, callback) {
|
|
152
|
-
encoding ||= enc;
|
|
153
|
-
let b = typeof chunk === "string"
|
|
154
|
-
? Buffer.from(chunk)
|
|
155
|
-
: chunk as Buffer;
|
|
156
|
-
buffer = buffer
|
|
157
|
-
? Buffer.concat([buffer, b])
|
|
158
|
-
: b;
|
|
159
|
-
callback();
|
|
160
|
-
},
|
|
161
|
-
final(callback) {
|
|
162
|
-
resolve();
|
|
163
|
-
callback();
|
|
164
|
-
},
|
|
165
|
-
}), { end: true });
|
|
166
|
-
});
|
|
167
|
-
const text = buffer.toString(encoding as any);
|
|
168
|
-
return JSON.parse(text);
|
|
169
|
-
},
|
|
142
|
+
Object.defineProperty(this, "accepts", {
|
|
143
|
+
value,
|
|
144
|
+
enumerable: true,
|
|
145
|
+
configurable: true
|
|
146
|
+
});
|
|
170
147
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
148
|
+
return value( ... types);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
get query(): any {
|
|
152
|
+
throw new Error("Please decorate `Ensure.parseQuery` callee or call `await Ensure.parseQuery(this)` before accessing this member");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
get body(): any {
|
|
156
|
+
throw new Error("Please decorate `Ensure.parseBody` callee or call `await Ensure.parseBody(this)` before accessing this member");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get form(): any {
|
|
160
|
+
throw new Error("Please decorate `Ensure.parseForm` callee or call `await Ensure.parseForm(this)` before accessing this member");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
get params(): any {
|
|
164
|
+
throw new Error("Please decorate `Ensure.parseAll` callee or call `await Ensure.parseAll(this)` before accessing this member");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get sessionUser(): any {
|
|
168
|
+
throw new Error("Please decorate `Ensure.authorize` callee or call `await Ensure.authorize(this)` before accessing this member");
|
|
169
|
+
}
|
|
170
|
+
|
|
184
171
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
async asyncForm(this: WrappedRequest) {
|
|
188
|
-
let tempFolder: TempFolder;
|
|
189
|
-
const result: IFormData = {
|
|
190
|
-
fields: {},
|
|
191
|
-
files: []
|
|
192
|
-
};
|
|
193
|
-
const req = this;
|
|
194
|
-
const bb = busboy({ headers: req.headers, defParamCharset: "utf8" });
|
|
195
|
-
const tasks = [];
|
|
196
|
-
await new Promise((resolve, reject) => {
|
|
197
|
-
|
|
198
|
-
bb.on("field", (name, value) => {
|
|
199
|
-
result.fields[name] = value;
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
bb.on("file", (name, file, info) => {
|
|
203
|
-
if (!tempFolder) {
|
|
204
|
-
tempFolder = new TempFolder();
|
|
205
|
-
this.disposables.push(tempFolder);
|
|
206
|
-
}
|
|
207
|
-
const tf = tempFolder.get(info.filename, info.mimeType);
|
|
208
|
-
tasks.push(tf.writeAll(file).then(() => {
|
|
209
|
-
result.files.push(tf);
|
|
210
|
-
}));
|
|
211
|
-
});
|
|
212
|
-
bb.on("error", reject);
|
|
213
|
-
bb.on("close", resolve);
|
|
214
|
-
req.pipe(bb);
|
|
215
|
-
});
|
|
216
|
-
await Promise.all(tasks);
|
|
217
|
-
return result;
|
|
172
|
+
A[extendedSymbol] = c;
|
|
218
173
|
}
|
|
174
|
+
return c;
|
|
219
175
|
};
|
|
220
176
|
|
|
221
|
-
const
|
|
177
|
+
const extendResponse = (A: typeof ServerResponse | typeof Http2ServerResponse) => {
|
|
178
|
+
let c = A[extendedSymbol];
|
|
179
|
+
if (!c) {
|
|
180
|
+
c = class WrappedResponse extends A implements IWrappedResponse {
|
|
222
181
|
|
|
223
|
-
|
|
224
|
-
return () => new Promise<void>((resolve) => this.end(resolve));
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
asyncWrite() {
|
|
228
|
-
return (buffer: Buffer, start?: number, length?: number) => {
|
|
229
|
-
return new Promise((resolve) =>
|
|
230
|
-
this.write(buffer, resolve)
|
|
231
|
-
);
|
|
232
|
-
};
|
|
233
|
-
},
|
|
182
|
+
statusCode: number;
|
|
234
183
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const cv = this.getHeaders()["set-cookie"];
|
|
238
|
-
const cookies = Array.isArray(cv) ? cv : [cv];
|
|
239
|
-
const nk = cookies.filter((x) => !x.startsWith(name + "="));
|
|
240
|
-
nk.push(serialize(name, value, options));
|
|
241
|
-
this.setHeader("set-cookie", nk);
|
|
242
|
-
}
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
send(this: WrappedResponse) {
|
|
246
|
-
return async (data: Buffer | string, status: number = 200) => {
|
|
247
|
-
try {
|
|
248
|
-
this.statusCode = status;
|
|
249
|
-
this.writeHead(this.statusCode, this.getHeaders());
|
|
250
|
-
await new Promise<void>((resolve, reject) => {
|
|
251
|
-
this.write(data, (error) => error ? reject(error) : resolve());
|
|
252
|
-
});
|
|
253
|
-
return this.asyncEnd();
|
|
254
|
-
} catch (error) {
|
|
255
|
-
console.error(error);
|
|
184
|
+
asyncEnd(this: UnwrappedResponse) {
|
|
185
|
+
return new Promise<void>((resolve) => this.end(resolve));
|
|
256
186
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
etag?: boolean,
|
|
274
|
-
immutable?: boolean,
|
|
275
|
-
headers?: { [key: string]: string},
|
|
276
|
-
lastModified?: boolean
|
|
277
|
-
}) => {
|
|
278
|
-
/** Calculate Size of file */
|
|
279
|
-
const { size } = await stat(filePath);
|
|
280
|
-
const range = this.request.headers.range;
|
|
281
|
-
|
|
282
|
-
const lf = new LocalFile(filePath);
|
|
283
|
-
|
|
284
|
-
/** Check for Range header */
|
|
285
|
-
if (!range) {
|
|
286
|
-
this.writeHead(200, {
|
|
287
|
-
"Content-Length": size,
|
|
288
|
-
"Content-Type": "video/mp4"
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
await lf.writeTo(this);
|
|
292
|
-
|
|
293
|
-
return this.asyncEnd();
|
|
187
|
+
|
|
188
|
+
asyncWrite(this: UnwrappedResponse, buffer: Buffer, start?: number, length?: number) {
|
|
189
|
+
return new Promise<void>((resolve, reject) =>
|
|
190
|
+
this.write(buffer, (error) => error ? reject(error) : resolve())
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
cookie(this: UnwrappedResponse, name: string, value: string, options = {}) {
|
|
195
|
+
const headers = this.getHeaders();
|
|
196
|
+
const cv = headers["set-cookie"];
|
|
197
|
+
const cookies = Array.isArray(cv)
|
|
198
|
+
? cv
|
|
199
|
+
: (cv ? [cv] : []);
|
|
200
|
+
const nk = cookies.filter((x) => !x.startsWith(name + "="));
|
|
201
|
+
nk.push(serialize(name, value, options));
|
|
202
|
+
headers["set-cookie"] = nk;
|
|
294
203
|
}
|
|
295
204
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
end = end ? parseInt(end, 10) : size - 1;
|
|
300
|
-
|
|
301
|
-
if (!isNaN(start) && isNaN(end)) {
|
|
302
|
-
start = start;
|
|
303
|
-
end = size - 1;
|
|
205
|
+
setHeader(this: UnwrappedResponse, name: string, value: string) {
|
|
206
|
+
const headers = this.getHeaders();
|
|
207
|
+
headers[name] = value;
|
|
304
208
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
209
|
+
|
|
210
|
+
async send(this: UnwrappedResponse, data: Buffer | string, status: number = 200) {
|
|
211
|
+
try {
|
|
212
|
+
const wrapped = (this as any as WrappedResponse);
|
|
213
|
+
wrapped.statusCode = status;
|
|
214
|
+
this.writeHead(wrapped.statusCode, this.getHeaders());
|
|
215
|
+
await new Promise<void>((resolve, reject) => {
|
|
216
|
+
this.write(data, (error) => error ? reject(error) : resolve());
|
|
217
|
+
});
|
|
218
|
+
return (this as any).asyncEnd();
|
|
219
|
+
} catch (error) {
|
|
220
|
+
console.error(error);
|
|
221
|
+
}
|
|
308
222
|
}
|
|
309
223
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
"Content-Range": `bytes */${size}`
|
|
224
|
+
async sendRedirect(this: UnwrappedResponse, location: string, permanent = false) {
|
|
225
|
+
this.statusCode = 301;
|
|
226
|
+
this.writeHead(this.statusCode, {
|
|
227
|
+
location
|
|
315
228
|
});
|
|
316
|
-
return this.asyncEnd();
|
|
229
|
+
return (this as any as IWrappedResponse).asyncEnd();
|
|
317
230
|
}
|
|
318
231
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
232
|
+
async sendFile(this: UnwrappedResponse, filePath: string, options?: {
|
|
233
|
+
acceptRanges?: boolean,
|
|
234
|
+
cacheControl?: boolean,
|
|
235
|
+
maxAge?: number,
|
|
236
|
+
etag?: boolean,
|
|
237
|
+
immutable?: boolean,
|
|
238
|
+
headers?: { [key: string]: string},
|
|
239
|
+
lastModified?: boolean
|
|
240
|
+
}) {
|
|
241
|
+
/** Calculate Size of file */
|
|
242
|
+
const { size } = await stat(filePath);
|
|
243
|
+
const range = (this as any as IWrappedResponse).request.headers.range;
|
|
244
|
+
|
|
245
|
+
const lf = new LocalFile(filePath);
|
|
246
|
+
|
|
247
|
+
/** Check for Range header */
|
|
248
|
+
if (!range) {
|
|
249
|
+
this.writeHead(200, {
|
|
250
|
+
"Content-Length": size,
|
|
251
|
+
"Content-Type": "video/mp4"
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
await lf.writeTo(this);
|
|
255
|
+
|
|
256
|
+
return (this as any).asyncEnd();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Extracting Start and End value from Range Header */
|
|
260
|
+
let [start, end] = range.replace(/bytes=/, "").split("-") as any[];
|
|
261
|
+
start = parseInt(start, 10);
|
|
262
|
+
end = end ? parseInt(end, 10) : size - 1;
|
|
263
|
+
|
|
264
|
+
if (!isNaN(start) && isNaN(end)) {
|
|
265
|
+
start = start;
|
|
266
|
+
end = size - 1;
|
|
267
|
+
}
|
|
268
|
+
if (isNaN(start) && !isNaN(end)) {
|
|
269
|
+
start = size - end;
|
|
270
|
+
end = size - 1;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Handle unavailable range request
|
|
274
|
+
if (start >= size || end >= size) {
|
|
275
|
+
// Return the 416 Range Not Satisfiable.
|
|
276
|
+
this.writeHead(416, {
|
|
277
|
+
"Content-Range": `bytes */${size}`
|
|
278
|
+
});
|
|
279
|
+
return (this as any).asyncEnd();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** Sending Partial Content With HTTP Code 206 */
|
|
283
|
+
this.writeHead(206, {
|
|
284
|
+
"Content-Range": `bytes ${start}-${end}/${size}`,
|
|
285
|
+
"Accept-Ranges": "bytes",
|
|
286
|
+
"Content-Length": end - start + 1,
|
|
287
|
+
"Content-Type": "video/mp4"
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
await lf.writeTo(this, start, end);
|
|
291
|
+
|
|
292
|
+
}
|
|
329
293
|
}
|
|
330
|
-
}
|
|
331
|
-
|
|
294
|
+
}
|
|
295
|
+
return c;
|
|
296
|
+
}
|
|
297
|
+
|
|
332
298
|
|
|
333
299
|
export const Wrapped = {
|
|
334
300
|
request: (req: UnwrappedRequest) => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
get() {
|
|
340
|
-
const value = element.call(this);
|
|
341
|
-
Object.defineProperty(this, key, { value, enumerable: true, writable: false });
|
|
342
|
-
return value;
|
|
343
|
-
},
|
|
344
|
-
enumerable: true,
|
|
345
|
-
configurable: true
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
}
|
|
301
|
+
let prototype = Object.getPrototypeOf(req);
|
|
302
|
+
const { constructor } = prototype;
|
|
303
|
+
prototype = extendRequest(constructor);
|
|
304
|
+
Object.setPrototypeOf(req, prototype);
|
|
349
305
|
const wr = req as WrappedRequest;
|
|
350
306
|
wr.disposables = [];
|
|
351
|
-
return
|
|
307
|
+
return req;
|
|
352
308
|
},
|
|
353
309
|
|
|
354
310
|
response: (req: WrappedRequest, res: UnwrappedResponse) => {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
get() {
|
|
360
|
-
const value = element.call(this);
|
|
361
|
-
Object.defineProperty(this, key, { value, enumerable: true, writable: false });
|
|
362
|
-
return value;
|
|
363
|
-
},
|
|
364
|
-
enumerable: true,
|
|
365
|
-
configurable: true
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
}
|
|
311
|
+
let prototype = Object.getPrototypeOf(res);
|
|
312
|
+
const { constructor } = prototype;
|
|
313
|
+
prototype = extendResponse(constructor);
|
|
314
|
+
Object.setPrototypeOf(res, prototype);
|
|
369
315
|
const wr = res as WrappedResponse;
|
|
370
316
|
wr.request = req;
|
|
371
317
|
req.response = wr;
|
|
372
|
-
return
|
|
318
|
+
return res;
|
|
373
319
|
}
|
|
374
320
|
}
|