Skip to content

Commit

Permalink
feat: 几个类的继承关系
Browse files Browse the repository at this point in the history
  • Loading branch information
xuqingshan committed Aug 3, 2020
1 parent b9be5f3 commit c321b09
Show file tree
Hide file tree
Showing 2 changed files with 553 additions and 0 deletions.
225 changes: 225 additions & 0 deletions node相关/eggsource/几个class的继承关系/Application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
class Application extends EggApplication {

/**
* @class
* @param {Object} options - see {@link EggApplication}
*/
constructor(options = {}) {
options.type = 'application';
super(options);

// will auto set after 'server' event emit
this.server = null;

try {
this.loader.load();
} catch (e) {
// close gracefully
this[CLUSTER_CLIENTS].forEach(cluster.close);
throw e;
}

// dump config after loaded, ensure all the dynamic modifications will be recorded
const dumpStartTime = Date.now();
this.dumpConfig();
this.coreLogger.info('[egg:core] dump config after load, %s', ms(Date.now() - dumpStartTime));

this[WARN_CONFUSED_CONFIG]();
this[BIND_EVENTS]();
}

get [EGG_LOADER]() {
return AppWorkerLoader;
}
get [EGG_PATH]() {
return path.join(__dirname, '..');
}
[RESPONSE_RAW](socket, raw) {
/* istanbul ignore next */
if (!socket.writable) return;
if (!raw) return socket.end(DEFAULT_BAD_REQUEST_RESPONSE);

const body = (raw.body == null) ? DEFAULT_BAD_REQUEST_HTML : raw.body;
const headers = raw.headers || {};
const status = raw.status || 400;

let responseHeaderLines = '';
const firstLine = `HTTP/1.1 ${status} ${http.STATUS_CODES[status] || 'Unknown'}`;

// Not that safe because no validation for header keys.
// Refs: https://github.com/nodejs/node/blob/b38c81/lib/_http_outgoing.js#L451
for (const key of Object.keys(headers)) {
if (key.toLowerCase() === 'content-length') {
delete headers[key];
continue;
}
responseHeaderLines += `${key}: ${escapeHeaderValue(headers[key])}\r\n`;
}

responseHeaderLines += `Content-Length: ${Buffer.byteLength(body)}\r\n`;

socket.end(`${firstLine}\r\n${responseHeaderLines}\r\n${body.toString()}`);
}
onClientError(err, socket) {
// ignore when there is no http body, it almost like an ECONNRESET
if (err.rawPacket) {
this.logger.warn('A client (%s:%d) error [%s] occurred: %s',
socket.remoteAddress,
socket.remotePort,
err.code,
err.message);
}

if (typeof this.config.onClientError === 'function') {
const p = eggUtils.callFn(this.config.onClientError, [ err, socket, this ]);
p.then(ret => {
this[RESPONSE_RAW](socket, ret || {});
}).catch(err => {
this.logger.error(err);
this[RESPONSE_RAW](socket);
});
} else {
// because it's a raw socket object, we should return the raw HTTP response
// packet.
this[RESPONSE_RAW](socket);
}
}
onServer(server) {
// expose app.server
this.server = server;

/* istanbul ignore next */
graceful({
server: [ server ],
error: (err, throwErrorCount) => {
const originMessage = err.message;
if (originMessage) {
// shouldjs will override error property but only getter
// https://github.com/shouldjs/should.js/blob/889e22ebf19a06bc2747d24cf34b25cc00b37464/lib/assertion-error.js#L26
Object.defineProperty(err, 'message', {
get() {
return originMessage + ' (uncaughtException throw ' + throwErrorCount + ' times on pid:' + process.pid + ')';
},
configurable: true,
enumerable: false,
});
}
this.coreLogger.error(err);
},
});

server.on('clientError', (err, socket) => this.onClientError(err, socket));

// server timeout
if (is.number(this.config.serverTimeout)) server.setTimeout(this.config.serverTimeout);
}
get locals() {
if (!this[LOCALS]) {
this[LOCALS] = {};
}
return this[LOCALS];
}
set locals(val) {
if (!this[LOCALS]) {
this[LOCALS] = {};
}

assign(this[LOCALS], val);
}
handleRequest(ctx, fnMiddleware) {
this.emit('request', ctx);
onFinished(ctx.res, () => this.emit('response', ctx));
return super.handleRequest(ctx, fnMiddleware);
}
dumpConfig() {
super.dumpConfig();

// dump routers to router.json
const rundir = this.config.rundir;
const FULLPATH = this.loader.FileLoader.FULLPATH;
try {
const dumpRouterFile = path.join(rundir, 'router.json');
const routers = [];
for (const layer of this.router.stack) {
routers.push({
name: layer.name,
methods: layer.methods,
paramNames: layer.paramNames,
path: layer.path,
regexp: layer.regexp.toString(),
stack: layer.stack.map(stack => stack[FULLPATH] || stack._name || stack.name || 'anonymous'),
});
}
fs.writeFileSync(dumpRouterFile, JSON.stringify(routers, null, 2));
} catch (err) {
this.coreLogger.warn(`dumpConfig router.json error: ${err.message}`);
}
}
runInBackground(scope) {
const ctx = this.createAnonymousContext();
if (!scope.name) scope._name = eggUtils.getCalleeFromStack(true);
ctx.runInBackground(scope);
}
get keys() {
if (!this[KEYS]) {
if (!this.config.keys) {
if (this.config.env === 'local' || this.config.env === 'unittest') {
const configPath = path.join(this.config.baseDir, 'config/config.default.js');
console.error('Cookie need secret key to sign and encrypt.');
console.error('Please add `config.keys` in %s', configPath);
}
throw new Error('Please set config.keys first');
}

this[KEYS] = this.config.keys.split(',').map(s => s.trim());
}
return this[KEYS];
}

set keys(_) {
// ignore
}

get Helper() {
if (!this[HELPER]) {
/**
* The Helper class which can be used as utility function.
* We support developers to extend Helper through ${baseDir}/app/extend/helper.js ,
* then you can use all method on `ctx.helper` that is a instance of Helper.
*/
class Helper extends this.BaseContextClass {}
this[HELPER] = Helper;
}
return this[HELPER];
}
[BIND_EVENTS]() {
// Browser Cookie Limits: http://browsercookielimits.squawky.net/
this.on('cookieLimitExceed', ({ name, value, ctx }) => {
const err = new Error(`cookie ${name}'s length(${value.length}) exceed the limit(4093)`);
err.name = 'CookieLimitExceedError';
err.key = name;
err.cookie = value;
ctx.coreLogger.error(err);
});
// expose server to support websocket
this.once('server', server => this.onServer(server));
}
[WARN_CONFUSED_CONFIG]() {
const confusedConfigurations = this.config.confusedConfigurations;
Object.keys(confusedConfigurations).forEach(key => {
if (this.config[key] !== undefined) {
this.logger.warn('Unexpected config key `%s` exists, Please use `%s` instead.',
key, confusedConfigurations[key]);
}
});
}
}
/**
* 初始化时的关键点有两个:
* 1. this.loader.load();
*
* 2. this.dumpConfig();
*
* 1.是load各种东西,
*
*/
Loading

0 comments on commit c321b09

Please sign in to comment.