@based/functions 1.0.0
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/.turbo/turbo-build.log +4 -0
- package/dist/auth.d.ts +15 -0
- package/dist/auth.js +3 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +11 -0
- package/dist/client.js +7 -0
- package/dist/client.js.map +1 -0
- package/dist/context.d.ts +63 -0
- package/dist/context.js +25 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +0 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/functions.d.ts +24 -0
- package/dist/functions.js +3 -0
- package/dist/functions.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/network.d.ts +0 -0
- package/dist/network.js +3 -0
- package/dist/network.js.map +1 -0
- package/dist/query.d.ts +6 -0
- package/dist/query.js +7 -0
- package/dist/query.js.map +1 -0
- package/dist/types.d.ts +0 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/uws.d.ts +141 -0
- package/dist/uws.js +3 -0
- package/dist/uws.js.map +1 -0
- package/package.json +20 -0
- package/src/auth.ts +33 -0
- package/src/client.ts +17 -0
- package/src/context.ts +100 -0
- package/src/functions.ts +61 -0
- package/src/index.ts +5 -0
- package/src/query.ts +14 -0
- package/src/uws.ts +197 -0
- package/tsconfig.json +9 -0
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BasedFunctionClient } from './client';
|
|
2
|
+
import { HttpRequest } from './uws';
|
|
3
|
+
import { Context, WebSocketSession, HttpSession } from './context';
|
|
4
|
+
export declare type AuthState = {
|
|
5
|
+
token?: string;
|
|
6
|
+
userId?: string;
|
|
7
|
+
refreshToken?: string;
|
|
8
|
+
error?: string;
|
|
9
|
+
persistent?: boolean;
|
|
10
|
+
type?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare type Authorize = (based: BasedFunctionClient, context: Context<HttpSession | WebSocketSession>, name: string, // name as generic dope
|
|
13
|
+
payload?: any) => Promise<boolean>;
|
|
14
|
+
export declare type VerifyAuthState = (based: BasedFunctionClient, context: Context<HttpSession | WebSocketSession>, authState: AuthState) => true | AuthState;
|
|
15
|
+
export declare type AuthorizeConnection = (based: BasedFunctionClient, req: HttpRequest) => Promise<boolean>;
|
package/dist/auth.js
ADDED
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":""}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AuthState } from './auth';
|
|
2
|
+
import { Context } from './context';
|
|
3
|
+
import { BasedQuery } from './query';
|
|
4
|
+
export declare abstract class BasedFunctionClient {
|
|
5
|
+
server: any;
|
|
6
|
+
abstract call(name: string, payload?: any, ctx?: Context): Promise<any>;
|
|
7
|
+
abstract query(name: string, payload?: any): BasedQuery;
|
|
8
|
+
abstract stream(name: string, stream?: any, ctx?: Context): Promise<any>;
|
|
9
|
+
abstract sendAuthState(ctx: Context, authState: AuthState): void;
|
|
10
|
+
abstract renewAuthState(ctx: Context): void;
|
|
11
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAIA,MAAsB,mBAAmB;CAYxC;AAZD,kDAYC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { AuthState } from './auth';
|
|
2
|
+
import { WebSocket, HttpRequest, HttpResponse } from './uws';
|
|
3
|
+
import { parseQuery } from '@saulx/utils';
|
|
4
|
+
import { BasedFunctionClient } from './client';
|
|
5
|
+
export declare type WebSocketSession = {
|
|
6
|
+
state?: any;
|
|
7
|
+
query: string;
|
|
8
|
+
ua: string;
|
|
9
|
+
ip: string;
|
|
10
|
+
id: number;
|
|
11
|
+
method: string;
|
|
12
|
+
authState: AuthState;
|
|
13
|
+
obs: Set<number>;
|
|
14
|
+
unauthorizedObs: Set<{
|
|
15
|
+
id: number;
|
|
16
|
+
checksum: number;
|
|
17
|
+
name: string;
|
|
18
|
+
payload: any;
|
|
19
|
+
}>;
|
|
20
|
+
c?: Context<WebSocketSession>;
|
|
21
|
+
} & WebSocket;
|
|
22
|
+
export declare type HttpSession = {
|
|
23
|
+
state?: any;
|
|
24
|
+
res: HttpResponse;
|
|
25
|
+
req: HttpRequest;
|
|
26
|
+
query?: string;
|
|
27
|
+
parsedQuery?: ReturnType<typeof parseQuery>;
|
|
28
|
+
ua: string;
|
|
29
|
+
ip: string;
|
|
30
|
+
id: number;
|
|
31
|
+
authState: AuthState;
|
|
32
|
+
method: string;
|
|
33
|
+
corsSend?: boolean;
|
|
34
|
+
headers: {
|
|
35
|
+
'content-length'?: number;
|
|
36
|
+
'content-type'?: string;
|
|
37
|
+
'content-encoding'?: string;
|
|
38
|
+
encoding?: string;
|
|
39
|
+
} & {
|
|
40
|
+
[key: string]: string;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare type InternalSessionObservable = {
|
|
44
|
+
id: number;
|
|
45
|
+
name: string;
|
|
46
|
+
type: 'observable';
|
|
47
|
+
};
|
|
48
|
+
export declare type InternalSessionClient = {
|
|
49
|
+
client: BasedFunctionClient;
|
|
50
|
+
type: 'client';
|
|
51
|
+
};
|
|
52
|
+
export declare type InternalSession = InternalSessionClient | InternalSessionObservable;
|
|
53
|
+
export declare type MinimalExternalSession = {
|
|
54
|
+
ua: string;
|
|
55
|
+
ip: string;
|
|
56
|
+
};
|
|
57
|
+
export declare type Session = WebSocketSession | HttpSession | InternalSession | MinimalExternalSession;
|
|
58
|
+
export declare type Context<S extends Session = Session> = {
|
|
59
|
+
session?: S;
|
|
60
|
+
};
|
|
61
|
+
export declare const isHttpContext: (ctx: Context<Session>) => ctx is Context<HttpSession>;
|
|
62
|
+
export declare const isWsContext: (ctx: Context<Session>) => ctx is Context<WebSocketSession>;
|
|
63
|
+
export declare const isWsSession: (session: Session) => session is WebSocketSession;
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isWsSession = exports.isWsContext = exports.isHttpContext = void 0;
|
|
4
|
+
const isHttpContext = (ctx) => {
|
|
5
|
+
if ('res' in ctx?.session) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
return false;
|
|
9
|
+
};
|
|
10
|
+
exports.isHttpContext = isHttpContext;
|
|
11
|
+
const isWsContext = (ctx) => {
|
|
12
|
+
if (ctx.session && (0, exports.isWsSession)(ctx.session)) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
};
|
|
17
|
+
exports.isWsContext = isWsContext;
|
|
18
|
+
const isWsSession = (session) => {
|
|
19
|
+
if (!('res' in session) && 'ip' in session && 'id' in session) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
exports.isWsSession = isWsSession;
|
|
25
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";;;AA4EO,MAAM,aAAa,GAAG,CAC3B,GAAqB,EACQ,EAAE;IAC/B,IAAI,KAAK,IAAI,GAAG,EAAE,OAAO,EAAE;QACzB,OAAO,IAAI,CAAA;KACZ;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAPY,QAAA,aAAa,iBAOzB;AAEM,MAAM,WAAW,GAAG,CACzB,GAAqB,EACa,EAAE;IACpC,IAAI,GAAG,CAAC,OAAO,IAAI,IAAA,mBAAW,EAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QAC3C,OAAO,IAAI,CAAA;KACZ;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAPY,QAAA,WAAW,eAOvB;AAEM,MAAM,WAAW,GAAG,CAAC,OAAgB,EAA+B,EAAE;IAC3E,IAAI,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,EAAE;QAC7D,OAAO,IAAI,CAAA;KACZ;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AALY,QAAA,WAAW,eAKvB"}
|
package/dist/errors.d.ts
ADDED
|
File without changes
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,uDAAuD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Context, HttpSession } from './context';
|
|
3
|
+
import { BasedFunctionClient } from './client';
|
|
4
|
+
import { Stream } from 'stream';
|
|
5
|
+
export declare type ObservableUpdateFunction<K = any> = {
|
|
6
|
+
(data: K, checksum?: number, diff?: any, fromChecksum?: number, isDeflate?: boolean, rawData?: K, err?: any): void;
|
|
7
|
+
__internalObs__?: true;
|
|
8
|
+
};
|
|
9
|
+
export declare type ObserveErrorListener = (err: any) => void;
|
|
10
|
+
export declare type CustomHttpResponse = (result: any, payload: any, client: Context<HttpSession>) => Promise<boolean>;
|
|
11
|
+
export declare type BasedFunction<P = any, K = any> = (based: BasedFunctionClient, payload: P, ctx: Context) => Promise<K>;
|
|
12
|
+
export declare type StreamPayload<P = any> = {
|
|
13
|
+
payload?: P;
|
|
14
|
+
mimeType: string;
|
|
15
|
+
size: number;
|
|
16
|
+
stream: Stream & {
|
|
17
|
+
size: number;
|
|
18
|
+
receivedBytes: number;
|
|
19
|
+
};
|
|
20
|
+
fileName?: string;
|
|
21
|
+
extension?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare type BasedStreamFunction<P = any, K = any> = BasedFunction<StreamPayload<P>, K>;
|
|
24
|
+
export declare type BasedQueryFunction<P = any, K = any> = ((based: BasedFunctionClient, payload: P, update: ObservableUpdateFunction<K>) => Promise<() => void>) | ((based: BasedFunctionClient, payload: P, update: ObservableUpdateFunction<K>) => () => void);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functions.js","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./context"), exports);
|
|
18
|
+
__exportStar(require("./auth"), exports);
|
|
19
|
+
__exportStar(require("./client"), exports);
|
|
20
|
+
__exportStar(require("./functions"), exports);
|
|
21
|
+
__exportStar(require("./query"), exports);
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB;AACzB,yCAAsB;AACtB,2CAAwB;AACxB,8CAA2B;AAC3B,0CAAuB"}
|
|
File without changes
|
package/dist/network.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":""}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ObservableUpdateFunction, ObserveErrorListener } from './functions';
|
|
2
|
+
export declare abstract class BasedQuery {
|
|
3
|
+
abstract subscribe(onData: ObservableUpdateFunction, onError?: ObserveErrorListener): () => void;
|
|
4
|
+
abstract getWhen(condition: (data: any, checksum: number) => boolean): Promise<any>;
|
|
5
|
+
abstract get(): Promise<any>;
|
|
6
|
+
}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":";;;AAEA,MAAsB,UAAU;CAW/B;AAXD,gCAWC"}
|
package/dist/types.d.ts
ADDED
|
File without changes
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,iBAAiB"}
|
package/dist/uws.d.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export declare type RecognizedString = string | ArrayBuffer | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array;
|
|
2
|
+
/** A WebSocket connection that is valid from open to close event.
|
|
3
|
+
* Read more about this in the user manual.
|
|
4
|
+
*/
|
|
5
|
+
export interface WebSocket {
|
|
6
|
+
/** Sends a message. Make sure to check getBufferedAmount() before sending. Returns true for success, false for built up backpressure that will drain when time is given.
|
|
7
|
+
* Returning false does not mean nothing was sent, it only means backpressure was built up. This you can check by calling getBufferedAmount() afterwards.
|
|
8
|
+
*
|
|
9
|
+
* Make sure you properly understand the concept of backpressure. Check the backpressure example file.
|
|
10
|
+
*/
|
|
11
|
+
send(message: RecognizedString, isBinary?: boolean, compress?: boolean): boolean;
|
|
12
|
+
/** Returns the bytes buffered in backpressure. This is similar to the bufferedAmount property in the browser counterpart.
|
|
13
|
+
* Check backpressure example.
|
|
14
|
+
*/
|
|
15
|
+
getBufferedAmount(): number;
|
|
16
|
+
/** Gracefully closes this WebSocket. Immediately calls the close handler.
|
|
17
|
+
* A WebSocket close message is sent with code and shortMessage.
|
|
18
|
+
*/
|
|
19
|
+
end(code?: number, shortMessage?: RecognizedString): void;
|
|
20
|
+
/** Forcefully closes this WebSocket. Immediately calls the close handler.
|
|
21
|
+
* No WebSocket close message is sent.
|
|
22
|
+
*/
|
|
23
|
+
close(): void;
|
|
24
|
+
/** Sends a ping control message. Returns true on success in similar ways as WebSocket.send does (regarding backpressure). This helper function correlates to WebSocket::send(message, uWS::OpCode::PING, ...) in C++. */
|
|
25
|
+
ping(message?: RecognizedString): boolean;
|
|
26
|
+
/** Subscribe to a topic. */
|
|
27
|
+
subscribe(topic: RecognizedString): boolean;
|
|
28
|
+
/** Unsubscribe from a topic. Returns true on success, if the WebSocket was subscribed. */
|
|
29
|
+
unsubscribe(topic: RecognizedString): boolean;
|
|
30
|
+
/** Returns whether this websocket is subscribed to topic. */
|
|
31
|
+
isSubscribed(topic: RecognizedString): boolean;
|
|
32
|
+
/** Returns a list of topics this websocket is subscribed to. */
|
|
33
|
+
getTopics(): string[];
|
|
34
|
+
/** Publish a message under topic. Backpressure is managed according to maxBackpressure, closeOnBackpressureLimit settings.
|
|
35
|
+
* Order is guaranteed since v20.
|
|
36
|
+
*/
|
|
37
|
+
publish(topic: RecognizedString, message: RecognizedString, isBinary?: boolean, compress?: boolean): boolean;
|
|
38
|
+
/** See HttpResponse.cork. Takes a function in which the socket is corked (packing many sends into one single syscall/SSL block) */
|
|
39
|
+
cork(cb: () => void): WebSocket;
|
|
40
|
+
/** Returns the remote IP address. Note that the returned IP is binary, not text.
|
|
41
|
+
*
|
|
42
|
+
* IPv4 is 4 byte long and can be converted to text by printing every byte as a digit between 0 and 255.
|
|
43
|
+
* IPv6 is 16 byte long and can be converted to text in similar ways, but you typically print digits in HEX.
|
|
44
|
+
*
|
|
45
|
+
* See getRemoteAddressAsText() for a text version.
|
|
46
|
+
*/
|
|
47
|
+
getRemoteAddress(): ArrayBuffer;
|
|
48
|
+
/** Returns the remote IP address as text. See RecognizedString. */
|
|
49
|
+
getRemoteAddressAsText(): ArrayBuffer;
|
|
50
|
+
/** Arbitrary user data may be attached to this object. In C++ this is done by using getUserData(). */
|
|
51
|
+
[key: string]: any;
|
|
52
|
+
}
|
|
53
|
+
/** An HttpResponse is valid until either onAborted callback or any of the .end/.tryEnd calls succeed. You may attach user data to this object. */
|
|
54
|
+
export interface HttpResponse {
|
|
55
|
+
/** Writes the HTTP status message such as "200 OK".
|
|
56
|
+
* This has to be called first in any response, otherwise
|
|
57
|
+
* it will be called automatically with "200 OK".
|
|
58
|
+
*
|
|
59
|
+
* If you want to send custom headers in a WebSocket
|
|
60
|
+
* upgrade response, you have to call writeStatus with
|
|
61
|
+
* "101 Switching Protocols" before you call writeHeader,
|
|
62
|
+
* otherwise your first call to writeHeader will call
|
|
63
|
+
* writeStatus with "200 OK" and the upgrade will fail.
|
|
64
|
+
*
|
|
65
|
+
* As you can imagine, we format outgoing responses in a linear
|
|
66
|
+
* buffer, not in a hash table. You can read about this in
|
|
67
|
+
* the user manual under "corking".
|
|
68
|
+
*/
|
|
69
|
+
writeStatus(status: RecognizedString): HttpResponse;
|
|
70
|
+
/** Writes key and value to HTTP response.
|
|
71
|
+
* See writeStatus and corking.
|
|
72
|
+
*/
|
|
73
|
+
writeHeader(key: RecognizedString, value: RecognizedString): HttpResponse;
|
|
74
|
+
/** Enters or continues chunked encoding mode. Writes part of the response. End with zero length write. Returns true if no backpressure was added. */
|
|
75
|
+
write(chunk: RecognizedString): boolean;
|
|
76
|
+
/** Ends this response by copying the contents of body. */
|
|
77
|
+
end(body?: RecognizedString, closeConnection?: boolean): HttpResponse;
|
|
78
|
+
/** Ends this response, or tries to, by streaming appropriately sized chunks of body. Use in conjunction with onWritable. Returns tuple [ok, hasResponded]. */
|
|
79
|
+
tryEnd(fullBodyOrChunk: RecognizedString, totalSize: number): [boolean, boolean];
|
|
80
|
+
/** Immediately force closes the connection. Any onAborted callback will run. */
|
|
81
|
+
close(): HttpResponse;
|
|
82
|
+
/** Returns the global byte write offset for this response. Use with onWritable. */
|
|
83
|
+
getWriteOffset(): number;
|
|
84
|
+
/** Registers a handler for writable events. Continue failed write attempts in here.
|
|
85
|
+
* You MUST return true for success, false for failure.
|
|
86
|
+
* Writing nothing is always success, so by default you must return true.
|
|
87
|
+
*/
|
|
88
|
+
onWritable(handler: (offset: number) => boolean): HttpResponse;
|
|
89
|
+
/** Every HttpResponse MUST have an attached abort handler IF you do not respond
|
|
90
|
+
* to it immediately inside of the callback. Returning from an Http request handler
|
|
91
|
+
* without attaching (by calling onAborted) an abort handler is ill-use and will termiante.
|
|
92
|
+
* When this event emits, the response has been aborted and may not be used. */
|
|
93
|
+
onAborted(handler: () => void): HttpResponse;
|
|
94
|
+
/** Handler for reading data from POST and such requests. You MUST copy the data of chunk if isLast is not true. We Neuter ArrayBuffers on return, making it zero length. */
|
|
95
|
+
onData(handler: (chunk: ArrayBuffer, isLast: boolean) => void): HttpResponse;
|
|
96
|
+
/** Returns the remote IP address in binary format (4 or 16 bytes). */
|
|
97
|
+
getRemoteAddress(): ArrayBuffer;
|
|
98
|
+
/** Returns the remote IP address as text. */
|
|
99
|
+
getRemoteAddressAsText(): ArrayBuffer;
|
|
100
|
+
/** Returns the remote IP address in binary format (4 or 16 bytes), as reported by the PROXY Protocol v2 compatible proxy. */
|
|
101
|
+
getProxiedRemoteAddress(): ArrayBuffer;
|
|
102
|
+
/** Returns the remote IP address as text, as reported by the PROXY Protocol v2 compatible proxy. */
|
|
103
|
+
getProxiedRemoteAddressAsText(): ArrayBuffer;
|
|
104
|
+
/** Corking a response is a performance improvement in both CPU and network, as you ready the IO system for writing multiple chunks at once.
|
|
105
|
+
* By default, you're corked in the immediately executing top portion of the route handler. In all other cases, such as when returning from
|
|
106
|
+
* await, or when being called back from an async database request or anything that isn't directly executing in the route handler, you'll want
|
|
107
|
+
* to cork before calling writeStatus, writeHeader or just write. Corking takes a callback in which you execute the writeHeader, writeStatus and
|
|
108
|
+
* such calls, in one atomic IO operation. This is important, not only for TCP but definitely for TLS where each write would otherwise result
|
|
109
|
+
* in one TLS block being sent off, each with one send syscall.
|
|
110
|
+
*
|
|
111
|
+
* Example usage:
|
|
112
|
+
*
|
|
113
|
+
* res.cork(() => {
|
|
114
|
+
* res.writeStatus("200 OK").writeHeader("Some", "Value").write("Hello world!");
|
|
115
|
+
* });
|
|
116
|
+
*/
|
|
117
|
+
cork(cb: () => void): HttpResponse;
|
|
118
|
+
/** Upgrades a HttpResponse to a WebSocket. See UpgradeAsync, UpgradeSync example files. */
|
|
119
|
+
upgrade<T>(userData: T, secWebSocketKey: RecognizedString, secWebSocketProtocol: RecognizedString, secWebSocketExtensions: RecognizedString, context: any): void;
|
|
120
|
+
/** Arbitrary user data may be attached to this object */
|
|
121
|
+
[key: string]: any;
|
|
122
|
+
}
|
|
123
|
+
/** An HttpRequest is stack allocated and only accessible during the callback invocation. */
|
|
124
|
+
export interface HttpRequest {
|
|
125
|
+
/** Returns the lowercased header value or empty string. */
|
|
126
|
+
getHeader(lowerCaseKey: RecognizedString): string;
|
|
127
|
+
/** Returns the parsed parameter at index. Corresponds to route. */
|
|
128
|
+
getParameter(index: number): string;
|
|
129
|
+
/** Returns the URL including initial /slash */
|
|
130
|
+
getUrl(): string;
|
|
131
|
+
/** Returns the HTTP method, useful for "any" routes. */
|
|
132
|
+
getMethod(): string;
|
|
133
|
+
/** Returns the raw querystring (the part of URL after ? sign) or empty string. */
|
|
134
|
+
getQuery(): string;
|
|
135
|
+
/** Returns a decoded query parameter value or empty string. */
|
|
136
|
+
getQuery(key: string): string;
|
|
137
|
+
/** Loops over all headers. */
|
|
138
|
+
forEach(cb: (key: string, value: string) => void): void;
|
|
139
|
+
/** Setting yield to true is to say that this route handler did not handle the route, causing the router to continue looking for a matching route handler, or fail. */
|
|
140
|
+
setYield(y: boolean): HttpRequest;
|
|
141
|
+
}
|
package/dist/uws.js
ADDED
package/dist/uws.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uws.js","sourceRoot":"","sources":["../src/uws.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@based/functions",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "npx tsc",
|
|
8
|
+
"watch": "npm run build -- --watch",
|
|
9
|
+
"clean": "rimraf {.turbo,dist,node_modules}"
|
|
10
|
+
},
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@saulx/utils": "^3.2.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"ts-node": "10.9.1",
|
|
17
|
+
"typescript": "^4.3.5",
|
|
18
|
+
"rimraf": "^3.0.2"
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/auth.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BasedFunctionClient } from './client'
|
|
2
|
+
import { HttpRequest } from './uws'
|
|
3
|
+
import { Context, WebSocketSession, HttpSession } from './context'
|
|
4
|
+
|
|
5
|
+
export type AuthState = {
|
|
6
|
+
token?: string
|
|
7
|
+
userId?: string
|
|
8
|
+
refreshToken?: string
|
|
9
|
+
error?: string
|
|
10
|
+
persistent?: boolean
|
|
11
|
+
type?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type Authorize = (
|
|
15
|
+
based: BasedFunctionClient,
|
|
16
|
+
context: Context<HttpSession | WebSocketSession>,
|
|
17
|
+
name: string, // name as generic dope
|
|
18
|
+
payload?: any
|
|
19
|
+
) => Promise<boolean>
|
|
20
|
+
|
|
21
|
+
// True - its the same all good
|
|
22
|
+
// AuthState - new auth state send it
|
|
23
|
+
// if error send error state (and reject)
|
|
24
|
+
export type VerifyAuthState = (
|
|
25
|
+
based: BasedFunctionClient,
|
|
26
|
+
context: Context<HttpSession | WebSocketSession>,
|
|
27
|
+
authState: AuthState
|
|
28
|
+
) => true | AuthState
|
|
29
|
+
|
|
30
|
+
export type AuthorizeConnection = (
|
|
31
|
+
based: BasedFunctionClient,
|
|
32
|
+
req: HttpRequest
|
|
33
|
+
) => Promise<boolean>
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AuthState } from './auth'
|
|
2
|
+
import { Context } from './context'
|
|
3
|
+
import { BasedQuery } from './query'
|
|
4
|
+
|
|
5
|
+
export abstract class BasedFunctionClient {
|
|
6
|
+
server: any
|
|
7
|
+
|
|
8
|
+
abstract call(name: string, payload?: any, ctx?: Context): Promise<any>
|
|
9
|
+
|
|
10
|
+
abstract query(name: string, payload?: any): BasedQuery
|
|
11
|
+
|
|
12
|
+
abstract stream(name: string, stream?: any, ctx?: Context): Promise<any>
|
|
13
|
+
|
|
14
|
+
abstract sendAuthState(ctx: Context, authState: AuthState): void
|
|
15
|
+
|
|
16
|
+
abstract renewAuthState(ctx: Context): void
|
|
17
|
+
}
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { AuthState } from './auth'
|
|
2
|
+
import { WebSocket, HttpRequest, HttpResponse } from './uws'
|
|
3
|
+
import { parseQuery } from '@saulx/utils'
|
|
4
|
+
import { BasedFunctionClient } from './client'
|
|
5
|
+
|
|
6
|
+
export type WebSocketSession = {
|
|
7
|
+
// State can be used for anyting - for us the based class instance
|
|
8
|
+
state?: any
|
|
9
|
+
query: string
|
|
10
|
+
ua: string
|
|
11
|
+
ip: string
|
|
12
|
+
id: number // client-id
|
|
13
|
+
method: string
|
|
14
|
+
authState: AuthState
|
|
15
|
+
obs: Set<number>
|
|
16
|
+
unauthorizedObs: Set<{
|
|
17
|
+
id: number
|
|
18
|
+
checksum: number
|
|
19
|
+
name: string
|
|
20
|
+
payload: any
|
|
21
|
+
}>
|
|
22
|
+
// Optimization so we dont need to keep track of websockets outside of uws
|
|
23
|
+
c?: Context<WebSocketSession>
|
|
24
|
+
} & WebSocket
|
|
25
|
+
|
|
26
|
+
export type HttpSession = {
|
|
27
|
+
// State can be used for anyting - for us the based class instance
|
|
28
|
+
state?: any
|
|
29
|
+
res: HttpResponse
|
|
30
|
+
req: HttpRequest
|
|
31
|
+
query?: string
|
|
32
|
+
parsedQuery?: ReturnType<typeof parseQuery>
|
|
33
|
+
ua: string
|
|
34
|
+
ip: string
|
|
35
|
+
id: number // client-id
|
|
36
|
+
authState: AuthState
|
|
37
|
+
method: string
|
|
38
|
+
corsSend?: boolean
|
|
39
|
+
headers: {
|
|
40
|
+
'content-length'?: number
|
|
41
|
+
'content-type'?: string
|
|
42
|
+
'content-encoding'?: string
|
|
43
|
+
encoding?: string
|
|
44
|
+
} & { [key: string]: string }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type InternalSessionObservable = {
|
|
48
|
+
id: number
|
|
49
|
+
name: string
|
|
50
|
+
type: 'observable'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type InternalSessionClient = {
|
|
54
|
+
client: BasedFunctionClient
|
|
55
|
+
type: 'client'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Internal session for internal functions
|
|
59
|
+
export type InternalSession = InternalSessionClient | InternalSessionObservable
|
|
60
|
+
|
|
61
|
+
// used for minimal security errors (e.g. rate limit)
|
|
62
|
+
export type MinimalExternalSession = {
|
|
63
|
+
ua: string
|
|
64
|
+
ip: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type Session =
|
|
68
|
+
| WebSocketSession
|
|
69
|
+
| HttpSession
|
|
70
|
+
| InternalSession
|
|
71
|
+
| MinimalExternalSession
|
|
72
|
+
|
|
73
|
+
export type Context<S extends Session = Session> = {
|
|
74
|
+
session?: S
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const isHttpContext = (
|
|
78
|
+
ctx: Context<Session>
|
|
79
|
+
): ctx is Context<HttpSession> => {
|
|
80
|
+
if ('res' in ctx?.session) {
|
|
81
|
+
return true
|
|
82
|
+
}
|
|
83
|
+
return false
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const isWsContext = (
|
|
87
|
+
ctx: Context<Session>
|
|
88
|
+
): ctx is Context<WebSocketSession> => {
|
|
89
|
+
if (ctx.session && isWsSession(ctx.session)) {
|
|
90
|
+
return true
|
|
91
|
+
}
|
|
92
|
+
return false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export const isWsSession = (session: Session): session is WebSocketSession => {
|
|
96
|
+
if (!('res' in session) && 'ip' in session && 'id' in session) {
|
|
97
|
+
return true
|
|
98
|
+
}
|
|
99
|
+
return false
|
|
100
|
+
}
|
package/src/functions.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Context, HttpSession } from './context'
|
|
2
|
+
import { BasedFunctionClient } from './client'
|
|
3
|
+
import { Stream } from 'stream'
|
|
4
|
+
|
|
5
|
+
export type ObservableUpdateFunction<K = any> = {
|
|
6
|
+
(
|
|
7
|
+
data: K,
|
|
8
|
+
checksum?: number,
|
|
9
|
+
diff?: any,
|
|
10
|
+
fromChecksum?: number,
|
|
11
|
+
isDeflate?: boolean,
|
|
12
|
+
rawData?: K,
|
|
13
|
+
// todo fix there errors TODO: make extra package 'errors' for client and server
|
|
14
|
+
err?: any
|
|
15
|
+
): void
|
|
16
|
+
__internalObs__?: true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// TODO: use error package
|
|
20
|
+
export type ObserveErrorListener = (err: any) => void
|
|
21
|
+
|
|
22
|
+
export type CustomHttpResponse = (
|
|
23
|
+
result: any,
|
|
24
|
+
payload: any,
|
|
25
|
+
client: Context<HttpSession>
|
|
26
|
+
) => Promise<boolean>
|
|
27
|
+
|
|
28
|
+
export type BasedFunction<P = any, K = any> = (
|
|
29
|
+
based: BasedFunctionClient,
|
|
30
|
+
payload: P,
|
|
31
|
+
ctx: Context
|
|
32
|
+
) => Promise<K>
|
|
33
|
+
|
|
34
|
+
export type StreamPayload<P = any> = {
|
|
35
|
+
payload?: P
|
|
36
|
+
mimeType: string
|
|
37
|
+
size: number
|
|
38
|
+
stream: Stream & {
|
|
39
|
+
size: number
|
|
40
|
+
receivedBytes: number
|
|
41
|
+
}
|
|
42
|
+
fileName?: string
|
|
43
|
+
extension?: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type BasedStreamFunction<P = any, K = any> = BasedFunction<
|
|
47
|
+
StreamPayload<P>,
|
|
48
|
+
K
|
|
49
|
+
>
|
|
50
|
+
|
|
51
|
+
export type BasedQueryFunction<P = any, K = any> =
|
|
52
|
+
| ((
|
|
53
|
+
based: BasedFunctionClient,
|
|
54
|
+
payload: P,
|
|
55
|
+
update: ObservableUpdateFunction<K>
|
|
56
|
+
) => Promise<() => void>)
|
|
57
|
+
| ((
|
|
58
|
+
based: BasedFunctionClient,
|
|
59
|
+
payload: P,
|
|
60
|
+
update: ObservableUpdateFunction<K>
|
|
61
|
+
) => () => void)
|
package/src/index.ts
ADDED
package/src/query.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ObservableUpdateFunction, ObserveErrorListener } from './functions'
|
|
2
|
+
|
|
3
|
+
export abstract class BasedQuery {
|
|
4
|
+
abstract subscribe(
|
|
5
|
+
onData: ObservableUpdateFunction,
|
|
6
|
+
onError?: ObserveErrorListener
|
|
7
|
+
): () => void
|
|
8
|
+
|
|
9
|
+
abstract getWhen(
|
|
10
|
+
condition: (data: any, checksum: number) => boolean
|
|
11
|
+
): Promise<any>
|
|
12
|
+
|
|
13
|
+
abstract get(): Promise<any>
|
|
14
|
+
}
|
package/src/uws.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
export type RecognizedString =
|
|
2
|
+
| string
|
|
3
|
+
| ArrayBuffer
|
|
4
|
+
| Uint8Array
|
|
5
|
+
| Int8Array
|
|
6
|
+
| Uint16Array
|
|
7
|
+
| Int16Array
|
|
8
|
+
| Uint32Array
|
|
9
|
+
| Int32Array
|
|
10
|
+
| Float32Array
|
|
11
|
+
| Float64Array
|
|
12
|
+
|
|
13
|
+
/** A WebSocket connection that is valid from open to close event.
|
|
14
|
+
* Read more about this in the user manual.
|
|
15
|
+
*/
|
|
16
|
+
export interface WebSocket {
|
|
17
|
+
/** Sends a message. Make sure to check getBufferedAmount() before sending. Returns true for success, false for built up backpressure that will drain when time is given.
|
|
18
|
+
* Returning false does not mean nothing was sent, it only means backpressure was built up. This you can check by calling getBufferedAmount() afterwards.
|
|
19
|
+
*
|
|
20
|
+
* Make sure you properly understand the concept of backpressure. Check the backpressure example file.
|
|
21
|
+
*/
|
|
22
|
+
send(
|
|
23
|
+
message: RecognizedString,
|
|
24
|
+
isBinary?: boolean,
|
|
25
|
+
compress?: boolean
|
|
26
|
+
): boolean
|
|
27
|
+
|
|
28
|
+
/** Returns the bytes buffered in backpressure. This is similar to the bufferedAmount property in the browser counterpart.
|
|
29
|
+
* Check backpressure example.
|
|
30
|
+
*/
|
|
31
|
+
getBufferedAmount(): number
|
|
32
|
+
|
|
33
|
+
/** Gracefully closes this WebSocket. Immediately calls the close handler.
|
|
34
|
+
* A WebSocket close message is sent with code and shortMessage.
|
|
35
|
+
*/
|
|
36
|
+
end(code?: number, shortMessage?: RecognizedString): void
|
|
37
|
+
|
|
38
|
+
/** Forcefully closes this WebSocket. Immediately calls the close handler.
|
|
39
|
+
* No WebSocket close message is sent.
|
|
40
|
+
*/
|
|
41
|
+
close(): void
|
|
42
|
+
|
|
43
|
+
/** Sends a ping control message. Returns true on success in similar ways as WebSocket.send does (regarding backpressure). This helper function correlates to WebSocket::send(message, uWS::OpCode::PING, ...) in C++. */
|
|
44
|
+
ping(message?: RecognizedString): boolean
|
|
45
|
+
|
|
46
|
+
/** Subscribe to a topic. */
|
|
47
|
+
subscribe(topic: RecognizedString): boolean
|
|
48
|
+
|
|
49
|
+
/** Unsubscribe from a topic. Returns true on success, if the WebSocket was subscribed. */
|
|
50
|
+
unsubscribe(topic: RecognizedString): boolean
|
|
51
|
+
|
|
52
|
+
/** Returns whether this websocket is subscribed to topic. */
|
|
53
|
+
isSubscribed(topic: RecognizedString): boolean
|
|
54
|
+
|
|
55
|
+
/** Returns a list of topics this websocket is subscribed to. */
|
|
56
|
+
getTopics(): string[]
|
|
57
|
+
|
|
58
|
+
/** Publish a message under topic. Backpressure is managed according to maxBackpressure, closeOnBackpressureLimit settings.
|
|
59
|
+
* Order is guaranteed since v20.
|
|
60
|
+
*/
|
|
61
|
+
publish(
|
|
62
|
+
topic: RecognizedString,
|
|
63
|
+
message: RecognizedString,
|
|
64
|
+
isBinary?: boolean,
|
|
65
|
+
compress?: boolean
|
|
66
|
+
): boolean
|
|
67
|
+
|
|
68
|
+
/** See HttpResponse.cork. Takes a function in which the socket is corked (packing many sends into one single syscall/SSL block) */
|
|
69
|
+
cork(cb: () => void): WebSocket
|
|
70
|
+
|
|
71
|
+
/** Returns the remote IP address. Note that the returned IP is binary, not text.
|
|
72
|
+
*
|
|
73
|
+
* IPv4 is 4 byte long and can be converted to text by printing every byte as a digit between 0 and 255.
|
|
74
|
+
* IPv6 is 16 byte long and can be converted to text in similar ways, but you typically print digits in HEX.
|
|
75
|
+
*
|
|
76
|
+
* See getRemoteAddressAsText() for a text version.
|
|
77
|
+
*/
|
|
78
|
+
getRemoteAddress(): ArrayBuffer
|
|
79
|
+
|
|
80
|
+
/** Returns the remote IP address as text. See RecognizedString. */
|
|
81
|
+
getRemoteAddressAsText(): ArrayBuffer
|
|
82
|
+
|
|
83
|
+
/** Arbitrary user data may be attached to this object. In C++ this is done by using getUserData(). */
|
|
84
|
+
[key: string]: any
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** An HttpResponse is valid until either onAborted callback or any of the .end/.tryEnd calls succeed. You may attach user data to this object. */
|
|
88
|
+
export interface HttpResponse {
|
|
89
|
+
/** Writes the HTTP status message such as "200 OK".
|
|
90
|
+
* This has to be called first in any response, otherwise
|
|
91
|
+
* it will be called automatically with "200 OK".
|
|
92
|
+
*
|
|
93
|
+
* If you want to send custom headers in a WebSocket
|
|
94
|
+
* upgrade response, you have to call writeStatus with
|
|
95
|
+
* "101 Switching Protocols" before you call writeHeader,
|
|
96
|
+
* otherwise your first call to writeHeader will call
|
|
97
|
+
* writeStatus with "200 OK" and the upgrade will fail.
|
|
98
|
+
*
|
|
99
|
+
* As you can imagine, we format outgoing responses in a linear
|
|
100
|
+
* buffer, not in a hash table. You can read about this in
|
|
101
|
+
* the user manual under "corking".
|
|
102
|
+
*/
|
|
103
|
+
writeStatus(status: RecognizedString): HttpResponse
|
|
104
|
+
/** Writes key and value to HTTP response.
|
|
105
|
+
* See writeStatus and corking.
|
|
106
|
+
*/
|
|
107
|
+
writeHeader(key: RecognizedString, value: RecognizedString): HttpResponse
|
|
108
|
+
/** Enters or continues chunked encoding mode. Writes part of the response. End with zero length write. Returns true if no backpressure was added. */
|
|
109
|
+
write(chunk: RecognizedString): boolean
|
|
110
|
+
/** Ends this response by copying the contents of body. */
|
|
111
|
+
end(body?: RecognizedString, closeConnection?: boolean): HttpResponse
|
|
112
|
+
/** Ends this response, or tries to, by streaming appropriately sized chunks of body. Use in conjunction with onWritable. Returns tuple [ok, hasResponded]. */
|
|
113
|
+
tryEnd(
|
|
114
|
+
fullBodyOrChunk: RecognizedString,
|
|
115
|
+
totalSize: number
|
|
116
|
+
): [boolean, boolean]
|
|
117
|
+
|
|
118
|
+
/** Immediately force closes the connection. Any onAborted callback will run. */
|
|
119
|
+
close(): HttpResponse
|
|
120
|
+
|
|
121
|
+
/** Returns the global byte write offset for this response. Use with onWritable. */
|
|
122
|
+
getWriteOffset(): number
|
|
123
|
+
|
|
124
|
+
/** Registers a handler for writable events. Continue failed write attempts in here.
|
|
125
|
+
* You MUST return true for success, false for failure.
|
|
126
|
+
* Writing nothing is always success, so by default you must return true.
|
|
127
|
+
*/
|
|
128
|
+
onWritable(handler: (offset: number) => boolean): HttpResponse
|
|
129
|
+
|
|
130
|
+
/** Every HttpResponse MUST have an attached abort handler IF you do not respond
|
|
131
|
+
* to it immediately inside of the callback. Returning from an Http request handler
|
|
132
|
+
* without attaching (by calling onAborted) an abort handler is ill-use and will termiante.
|
|
133
|
+
* When this event emits, the response has been aborted and may not be used. */
|
|
134
|
+
onAborted(handler: () => void): HttpResponse
|
|
135
|
+
|
|
136
|
+
/** Handler for reading data from POST and such requests. You MUST copy the data of chunk if isLast is not true. We Neuter ArrayBuffers on return, making it zero length. */
|
|
137
|
+
onData(handler: (chunk: ArrayBuffer, isLast: boolean) => void): HttpResponse
|
|
138
|
+
|
|
139
|
+
/** Returns the remote IP address in binary format (4 or 16 bytes). */
|
|
140
|
+
getRemoteAddress(): ArrayBuffer
|
|
141
|
+
|
|
142
|
+
/** Returns the remote IP address as text. */
|
|
143
|
+
getRemoteAddressAsText(): ArrayBuffer
|
|
144
|
+
|
|
145
|
+
/** Returns the remote IP address in binary format (4 or 16 bytes), as reported by the PROXY Protocol v2 compatible proxy. */
|
|
146
|
+
getProxiedRemoteAddress(): ArrayBuffer
|
|
147
|
+
|
|
148
|
+
/** Returns the remote IP address as text, as reported by the PROXY Protocol v2 compatible proxy. */
|
|
149
|
+
getProxiedRemoteAddressAsText(): ArrayBuffer
|
|
150
|
+
|
|
151
|
+
/** Corking a response is a performance improvement in both CPU and network, as you ready the IO system for writing multiple chunks at once.
|
|
152
|
+
* By default, you're corked in the immediately executing top portion of the route handler. In all other cases, such as when returning from
|
|
153
|
+
* await, or when being called back from an async database request or anything that isn't directly executing in the route handler, you'll want
|
|
154
|
+
* to cork before calling writeStatus, writeHeader or just write. Corking takes a callback in which you execute the writeHeader, writeStatus and
|
|
155
|
+
* such calls, in one atomic IO operation. This is important, not only for TCP but definitely for TLS where each write would otherwise result
|
|
156
|
+
* in one TLS block being sent off, each with one send syscall.
|
|
157
|
+
*
|
|
158
|
+
* Example usage:
|
|
159
|
+
*
|
|
160
|
+
* res.cork(() => {
|
|
161
|
+
* res.writeStatus("200 OK").writeHeader("Some", "Value").write("Hello world!");
|
|
162
|
+
* });
|
|
163
|
+
*/
|
|
164
|
+
cork(cb: () => void): HttpResponse
|
|
165
|
+
|
|
166
|
+
/** Upgrades a HttpResponse to a WebSocket. See UpgradeAsync, UpgradeSync example files. */
|
|
167
|
+
upgrade<T>(
|
|
168
|
+
userData: T,
|
|
169
|
+
secWebSocketKey: RecognizedString,
|
|
170
|
+
secWebSocketProtocol: RecognizedString,
|
|
171
|
+
secWebSocketExtensions: RecognizedString,
|
|
172
|
+
context: any
|
|
173
|
+
): void
|
|
174
|
+
|
|
175
|
+
/** Arbitrary user data may be attached to this object */
|
|
176
|
+
[key: string]: any
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** An HttpRequest is stack allocated and only accessible during the callback invocation. */
|
|
180
|
+
export interface HttpRequest {
|
|
181
|
+
/** Returns the lowercased header value or empty string. */
|
|
182
|
+
getHeader(lowerCaseKey: RecognizedString): string
|
|
183
|
+
/** Returns the parsed parameter at index. Corresponds to route. */
|
|
184
|
+
getParameter(index: number): string
|
|
185
|
+
/** Returns the URL including initial /slash */
|
|
186
|
+
getUrl(): string
|
|
187
|
+
/** Returns the HTTP method, useful for "any" routes. */
|
|
188
|
+
getMethod(): string
|
|
189
|
+
/** Returns the raw querystring (the part of URL after ? sign) or empty string. */
|
|
190
|
+
getQuery(): string
|
|
191
|
+
/** Returns a decoded query parameter value or empty string. */
|
|
192
|
+
getQuery(key: string): string
|
|
193
|
+
/** Loops over all headers. */
|
|
194
|
+
forEach(cb: (key: string, value: string) => void): void
|
|
195
|
+
/** Setting yield to true is to say that this route handler did not handle the route, causing the router to continue looking for a matching route handler, or fail. */
|
|
196
|
+
setYield(y: boolean): HttpRequest
|
|
197
|
+
}
|