@eggjs/koa 2.14.2

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/lib/context.js ADDED
@@ -0,0 +1,251 @@
1
+
2
+ 'use strict';
3
+
4
+ /**
5
+ * Module dependencies.
6
+ */
7
+
8
+ const util = require('util');
9
+ const createError = require('http-errors');
10
+ const httpAssert = require('http-assert');
11
+ const delegate = require('delegates');
12
+ const statuses = require('statuses');
13
+ const Cookies = require('cookies');
14
+
15
+ const COOKIES = Symbol('context#cookies');
16
+
17
+ /**
18
+ * Context prototype.
19
+ */
20
+
21
+ const proto = module.exports = {
22
+
23
+ /**
24
+ * util.inspect() implementation, which
25
+ * just returns the JSON output.
26
+ *
27
+ * @return {Object}
28
+ * @api public
29
+ */
30
+
31
+ inspect() {
32
+ if (this === proto) return this;
33
+ return this.toJSON();
34
+ },
35
+
36
+ /**
37
+ * Return JSON representation.
38
+ *
39
+ * Here we explicitly invoke .toJSON() on each
40
+ * object, as iteration will otherwise fail due
41
+ * to the getters and cause utilities such as
42
+ * clone() to fail.
43
+ *
44
+ * @return {Object}
45
+ * @api public
46
+ */
47
+
48
+ toJSON() {
49
+ return {
50
+ request: this.request.toJSON(),
51
+ response: this.response.toJSON(),
52
+ app: this.app.toJSON(),
53
+ originalUrl: this.originalUrl,
54
+ req: '<original node req>',
55
+ res: '<original node res>',
56
+ socket: '<original node socket>'
57
+ };
58
+ },
59
+
60
+ /**
61
+ * Similar to .throw(), adds assertion.
62
+ *
63
+ * this.assert(this.user, 401, 'Please login!');
64
+ *
65
+ * See: https://github.com/jshttp/http-assert
66
+ *
67
+ * @param {Mixed} test
68
+ * @param {Number} status
69
+ * @param {String} message
70
+ * @api public
71
+ */
72
+
73
+ assert: httpAssert,
74
+
75
+ /**
76
+ * Throw an error with `status` (default 500) and
77
+ * `msg`. Note that these are user-level
78
+ * errors, and the message may be exposed to the client.
79
+ *
80
+ * this.throw(403)
81
+ * this.throw(400, 'name required')
82
+ * this.throw('something exploded')
83
+ * this.throw(new Error('invalid'))
84
+ * this.throw(400, new Error('invalid'))
85
+ *
86
+ * See: https://github.com/jshttp/http-errors
87
+ *
88
+ * Note: `status` should only be passed as the first parameter.
89
+ *
90
+ * @param {String|Number|Error} err, msg or status
91
+ * @param {String|Number|Error} [err, msg or status]
92
+ * @param {Object} [props]
93
+ * @api public
94
+ */
95
+
96
+ throw(...args) {
97
+ throw createError(...args);
98
+ },
99
+
100
+ /**
101
+ * Default error handling.
102
+ *
103
+ * @param {Error} err
104
+ * @api private
105
+ */
106
+
107
+ onerror(err) {
108
+ // don't do anything if there is no error.
109
+ // this allows you to pass `this.onerror`
110
+ // to node-style callbacks.
111
+ if (null == err) return;
112
+
113
+ // When dealing with cross-globals a normal `instanceof` check doesn't work properly.
114
+ // See https://github.com/koajs/koa/issues/1466
115
+ // We can probably remove it once jest fixes https://github.com/facebook/jest/issues/2549.
116
+ const isNativeError =
117
+ Object.prototype.toString.call(err) === '[object Error]' ||
118
+ err instanceof Error;
119
+ if (!isNativeError) err = new Error(util.format('non-error thrown: %j', err));
120
+
121
+ let headerSent = false;
122
+ if (this.headerSent || !this.writable) {
123
+ headerSent = err.headerSent = true;
124
+ }
125
+
126
+ // delegate
127
+ this.app.emit('error', err, this);
128
+
129
+ // nothing we can do here other
130
+ // than delegate to the app-level
131
+ // handler and log.
132
+ if (headerSent) {
133
+ return;
134
+ }
135
+
136
+ const { res } = this;
137
+
138
+ // first unset all headers
139
+ /* istanbul ignore else */
140
+ if (typeof res.getHeaderNames === 'function') {
141
+ res.getHeaderNames().forEach(name => res.removeHeader(name));
142
+ } else {
143
+ res._headers = {}; // Node < 7.7
144
+ }
145
+
146
+ // then set those specified
147
+ this.set(err.headers);
148
+
149
+ // force text/plain
150
+ this.type = 'text';
151
+
152
+ let statusCode = err.status || err.statusCode;
153
+
154
+ // ENOENT support
155
+ if ('ENOENT' === err.code) statusCode = 404;
156
+
157
+ // default to 500
158
+ if ('number' !== typeof statusCode || !statuses[statusCode]) statusCode = 500;
159
+
160
+ // respond
161
+ const code = statuses[statusCode];
162
+ const msg = err.expose ? err.message : code;
163
+ this.status = err.status = statusCode;
164
+ this.length = Buffer.byteLength(msg);
165
+ res.end(msg);
166
+ },
167
+
168
+ get cookies() {
169
+ if (!this[COOKIES]) {
170
+ this[COOKIES] = new Cookies(this.req, this.res, {
171
+ keys: this.app.keys,
172
+ secure: this.request.secure
173
+ });
174
+ }
175
+ return this[COOKIES];
176
+ },
177
+
178
+ set cookies(_cookies) {
179
+ this[COOKIES] = _cookies;
180
+ }
181
+ };
182
+
183
+ /**
184
+ * Custom inspection implementation for newer Node.js versions.
185
+ *
186
+ * @return {Object}
187
+ * @api public
188
+ */
189
+
190
+ /* istanbul ignore else */
191
+ if (util.inspect.custom) {
192
+ module.exports[util.inspect.custom] = module.exports.inspect;
193
+ }
194
+
195
+ /**
196
+ * Response delegation.
197
+ */
198
+
199
+ delegate(proto, 'response')
200
+ .method('attachment')
201
+ .method('redirect')
202
+ .method('remove')
203
+ .method('vary')
204
+ .method('has')
205
+ .method('set')
206
+ .method('append')
207
+ .method('flushHeaders')
208
+ .access('status')
209
+ .access('message')
210
+ .access('body')
211
+ .access('length')
212
+ .access('type')
213
+ .access('lastModified')
214
+ .access('etag')
215
+ .getter('headerSent')
216
+ .getter('writable');
217
+
218
+ /**
219
+ * Request delegation.
220
+ */
221
+
222
+ delegate(proto, 'request')
223
+ .method('acceptsLanguages')
224
+ .method('acceptsEncodings')
225
+ .method('acceptsCharsets')
226
+ .method('accepts')
227
+ .method('get')
228
+ .method('is')
229
+ .access('querystring')
230
+ .access('idempotent')
231
+ .access('socket')
232
+ .access('search')
233
+ .access('method')
234
+ .access('query')
235
+ .access('path')
236
+ .access('url')
237
+ .access('accept')
238
+ .getter('origin')
239
+ .getter('href')
240
+ .getter('subdomains')
241
+ .getter('protocol')
242
+ .getter('host')
243
+ .getter('hostname')
244
+ .getter('URL')
245
+ .getter('header')
246
+ .getter('headers')
247
+ .getter('secure')
248
+ .getter('stale')
249
+ .getter('fresh')
250
+ .getter('ips')
251
+ .getter('ip');