2013-11-13 17:01:15 +00:00
|
|
|
|
2013-08-17 07:15:57 +00:00
|
|
|
/**
|
|
|
|
* Module dependencies.
|
|
|
|
*/
|
|
|
|
|
|
|
|
var debug = require('debug')('koa:context');
|
|
|
|
var http = require('http');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prototype.
|
|
|
|
*/
|
|
|
|
|
2013-11-14 02:34:15 +00:00
|
|
|
module.exports = {
|
2013-08-17 07:15:57 +00:00
|
|
|
|
2013-11-19 01:33:41 +00:00
|
|
|
/**
|
|
|
|
* Inspect implementation.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
* @api public
|
|
|
|
*/
|
|
|
|
|
|
|
|
inspect: function(){
|
|
|
|
return this.toJSON();
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return JSON representation.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
* @api public
|
|
|
|
*/
|
|
|
|
|
|
|
|
toJSON: function(){
|
|
|
|
return {
|
2013-12-02 17:08:01 +00:00
|
|
|
request: this.request,
|
|
|
|
response: this.response
|
2013-11-19 01:33:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Throw an error with `msg` and optional `status`
|
|
|
|
* defaulting to 500. Note that these are user-level
|
|
|
|
* errors, and the message may be exposed to the client.
|
|
|
|
*
|
2013-11-19 01:38:12 +00:00
|
|
|
* this.throw(403)
|
|
|
|
* this.throw('name required', 400)
|
|
|
|
* this.throw('something exploded')
|
2013-11-19 01:33:41 +00:00
|
|
|
*
|
|
|
|
* @param {String|Number} msg
|
|
|
|
* @param {Number} status
|
|
|
|
* @api public
|
|
|
|
*/
|
|
|
|
|
2013-11-19 01:38:12 +00:00
|
|
|
throw: function(msg, status){
|
2013-11-19 01:33:41 +00:00
|
|
|
// TODO: switch order... feels weird now that im used to express
|
|
|
|
if ('number' == typeof msg) {
|
|
|
|
var tmp = msg;
|
|
|
|
msg = http.STATUS_CODES[tmp];
|
|
|
|
status = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
var err = new Error(msg);
|
|
|
|
err.status = status || 500;
|
|
|
|
err.expose = true;
|
|
|
|
throw err;
|
|
|
|
},
|
|
|
|
|
2013-11-19 01:38:12 +00:00
|
|
|
/**
|
|
|
|
* Alias for .throw() for backwards compatibility.
|
|
|
|
* Do not use - will be removed in the future.
|
|
|
|
*
|
|
|
|
* @param {String|Number} msg
|
|
|
|
* @param {Number} status
|
|
|
|
* @api private
|
|
|
|
*/
|
|
|
|
|
|
|
|
error: function(msg, status){
|
2013-12-19 10:48:32 +00:00
|
|
|
console.warn('ctx.error is deprecated, use ctx.throw');
|
2013-11-19 01:38:12 +00:00
|
|
|
this.throw(msg, status);
|
|
|
|
},
|
|
|
|
|
2013-11-19 01:33:41 +00:00
|
|
|
/**
|
|
|
|
* Default error handling.
|
|
|
|
*
|
|
|
|
* @param {Error} err
|
|
|
|
* @api private
|
|
|
|
*/
|
|
|
|
|
|
|
|
onerror: function(err){
|
|
|
|
// don't do anything if there is no error.
|
|
|
|
// this allows you to pass `this.onerror`
|
|
|
|
// to node-style callbacks.
|
|
|
|
if (!err) return;
|
|
|
|
|
|
|
|
// nothing we can do here other
|
|
|
|
// than delegate to the app-level
|
|
|
|
// handler and log.
|
2013-12-18 01:37:35 +00:00
|
|
|
if (this.headerSent || !this.socket.writable) {
|
2013-11-19 01:33:41 +00:00
|
|
|
err.headerSent = true;
|
|
|
|
this.app.emit('error', err, this);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// delegate
|
|
|
|
this.app.emit('error', err, this);
|
|
|
|
|
|
|
|
// force text/plain
|
|
|
|
this.type = 'text';
|
|
|
|
|
|
|
|
// ENOENT support
|
|
|
|
if ('ENOENT' == err.code) err.status = 404;
|
|
|
|
|
|
|
|
// default to 500
|
|
|
|
err.status = err.status || 500;
|
|
|
|
|
|
|
|
// respond
|
|
|
|
var code = http.STATUS_CODES[err.status];
|
|
|
|
var msg = err.expose ? err.message : code;
|
|
|
|
this.status = err.status;
|
|
|
|
this.res.end(msg);
|
|
|
|
},
|
|
|
|
|
2013-08-17 07:15:57 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#header.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get header() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.header;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#url.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
get url() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.url;
|
2013-09-14 22:54:17 +00:00
|
|
|
},
|
2013-08-17 07:15:57 +00:00
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#url=.
|
2013-09-14 22:54:17 +00:00
|
|
|
*/
|
2013-08-28 02:30:35 +00:00
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
set url(val) {
|
2013-11-13 17:01:15 +00:00
|
|
|
this.request.url = val;
|
2013-08-28 02:30:35 +00:00
|
|
|
},
|
2013-08-21 04:24:18 +00:00
|
|
|
|
2013-08-28 02:30:35 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#method.
|
2013-08-28 02:30:35 +00:00
|
|
|
*/
|
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
get method() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.method;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#method=.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
set method(val) {
|
2013-11-13 17:01:15 +00:00
|
|
|
this.request.method = val;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Response#status.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-10-24 06:54:07 +00:00
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get status() {
|
|
|
|
return this.response.status;
|
2013-10-24 06:44:22 +00:00
|
|
|
},
|
2013-08-17 07:15:57 +00:00
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Response#status=.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
set status(val) {
|
2013-11-13 17:01:15 +00:00
|
|
|
this.response.status = val;
|
2013-10-24 06:44:22 +00:00
|
|
|
},
|
2013-08-17 07:15:57 +00:00
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Response#body.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
get body() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.response.body;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Response#body=.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
set body(val) {
|
2013-11-13 17:01:15 +00:00
|
|
|
this.response.body = val;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#path.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get path() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.path;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#path=.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
set path(val) {
|
|
|
|
this.request.path = val;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#query.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get query() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.query;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#query=.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
set query(val) {
|
|
|
|
this.request.query = val;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#querystring.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get querystring() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.querystring;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#querystring=.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
set querystring(val) {
|
|
|
|
this.request.querystring = val;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
2013-11-19 03:29:29 +00:00
|
|
|
/**
|
|
|
|
* Delegate to Request#search.
|
|
|
|
*/
|
|
|
|
|
|
|
|
get search() {
|
|
|
|
return this.request.search;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delegate to Request#search=.
|
|
|
|
*/
|
|
|
|
|
|
|
|
set search(val) {
|
|
|
|
this.request.search = val;
|
|
|
|
},
|
|
|
|
|
2013-08-17 07:15:57 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#host.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get host() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.host;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#fresh.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get fresh() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.fresh;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#stale.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get stale() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.stale;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#idempotent.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get idempotent() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.idempotent;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#socket.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get socket() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.socket;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#length.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
get length() {
|
2013-11-13 17:01:15 +00:00
|
|
|
return this.request.length;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
2013-09-14 22:54:17 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#length.
|
2013-09-14 22:54:17 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
set length(val) {
|
|
|
|
this.response.length = val;
|
2013-09-14 22:54:17 +00:00
|
|
|
},
|
|
|
|
|
2013-08-17 07:15:57 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#protocol.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get protocol() {
|
|
|
|
return this.request.protocol;
|
|
|
|
},
|
2013-08-17 07:15:57 +00:00
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
/**
|
|
|
|
* Delegate to Request#secure.
|
|
|
|
*/
|
2013-08-17 07:15:57 +00:00
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get secure() {
|
|
|
|
return this.request.secure;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#ip.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get ip() {
|
|
|
|
return this.request.ip;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#ips.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get ips() {
|
|
|
|
return this.request.ips;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#subdomains.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get subdomains() {
|
|
|
|
return this.request.subdomains;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Response#headerSent.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get headerSent() {
|
|
|
|
return this.response.headerSent;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Response#type=.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
set type(val) {
|
|
|
|
this.response.type = val;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#type.
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
get type() {
|
|
|
|
return this.request.type;
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
2013-11-20 22:09:49 +00:00
|
|
|
/**
|
|
|
|
* Delegate to Response#lastModified=.
|
|
|
|
*/
|
|
|
|
|
|
|
|
set lastModified(val) {
|
|
|
|
this.response.lastModified = val;
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delegate to Response#etag=.
|
|
|
|
*/
|
|
|
|
|
|
|
|
set etag(val) {
|
|
|
|
this.response.etag = val;
|
|
|
|
},
|
|
|
|
|
2013-11-24 13:06:35 +00:00
|
|
|
/**
|
|
|
|
* Delegate to Request#remove().
|
|
|
|
*/
|
|
|
|
|
|
|
|
remove: function() {
|
|
|
|
return this.response.remove.apply(this.response, arguments);
|
|
|
|
},
|
|
|
|
|
2013-08-17 07:15:57 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#accepts().
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
accepts: function() {
|
|
|
|
return this.request.accepts.apply(this.request, arguments);
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#acceptsCharsets().
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
acceptsCharsets: function() {
|
|
|
|
return this.request.acceptsCharsets.apply(this.request, arguments);
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#acceptsEncodings().
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
acceptsEncodings: function() {
|
|
|
|
return this.request.acceptsEncodings.apply(this.request, arguments);
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Request#acceptsLanguages().
|
2013-08-17 07:15:57 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
acceptsLanguages: function() {
|
|
|
|
return this.request.acceptsLanguages.apply(this.request, arguments);
|
2013-08-17 07:15:57 +00:00
|
|
|
},
|
2013-10-24 06:54:07 +00:00
|
|
|
|
2013-11-08 22:38:35 +00:00
|
|
|
/**
|
2013-11-13 17:01:15 +00:00
|
|
|
* Delegate to Response#vary().
|
2013-11-08 22:38:35 +00:00
|
|
|
*/
|
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
vary: function() {
|
|
|
|
return this.response.vary.apply(this.response, arguments);
|
2013-10-24 05:38:06 +00:00
|
|
|
},
|
2013-08-17 07:15:57 +00:00
|
|
|
|
2013-11-13 17:01:15 +00:00
|
|
|
/**
|
|
|
|
* Delegate to Request#is().
|
|
|
|
*/
|
|
|
|
|
|
|
|
is: function() {
|
|
|
|
return this.request.is.apply(this.request, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delegate to Response#append().
|
|
|
|
*/
|
|
|
|
|
|
|
|
append: function() {
|
|
|
|
return this.response.append.apply(this.response, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delegate to Request#get().
|
|
|
|
*/
|
|
|
|
|
|
|
|
get: function() {
|
|
|
|
return this.request.get.apply(this.request, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delegate to Response#set().
|
|
|
|
*/
|
|
|
|
|
|
|
|
set: function() {
|
|
|
|
return this.response.set.apply(this.response, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delegate to Response#redirect().
|
|
|
|
*/
|
|
|
|
|
|
|
|
redirect: function() {
|
|
|
|
return this.response.redirect.apply(this.response, arguments);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delegate to Response#attachment().
|
|
|
|
*/
|
|
|
|
|
|
|
|
attachment: function() {
|
|
|
|
return this.response.attachment.apply(this.response, arguments);
|
2013-11-14 02:34:15 +00:00
|
|
|
},
|
2013-12-19 16:53:48 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Invoke `fn` on socket errors and
|
|
|
|
* handle cleanup on response.
|
|
|
|
*
|
|
|
|
* @param {Function} fn
|
|
|
|
* @api private
|
|
|
|
*/
|
|
|
|
|
|
|
|
onSocketError: function(fn){
|
|
|
|
var sock = this.socket;
|
|
|
|
sock.once('error', fn);
|
|
|
|
this.res.on('finish', function(){
|
|
|
|
sock.removeListener('error', fn);
|
|
|
|
});
|
|
|
|
}
|
2013-08-17 07:15:57 +00:00
|
|
|
};
|