Skip to content

Commit

Permalink
feat: export CookieLimitExceedError
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Jan 1, 2025
1 parent e440fad commit d03a004
Show file tree
Hide file tree
Showing 9 changed files with 99 additions and 58 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "egg",
"version": "4.0.0-beta.11",
"version": "4.0.0-beta.12",
"engines": {
"node": ">= 18.19.0"
},
Expand Down Expand Up @@ -78,7 +78,7 @@
"formstream": "^1.5.1",
"koa-static": "^5.0.0",
"mm": "^3.4.0",
"pedding": "^1.1.0",
"pedding": "^2.0.0",
"prettier": "^2.7.1",
"rimraf": "6",
"runscript": "^2.0.1",
Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export * from './lib/egg.js';
export * from './lib/type.js';
export * from './lib/start.js';

// export errors
export * from './lib/error/index.js';

/**
* Start egg application with cluster mode
* @since 1.0.0
Expand Down
7 changes: 4 additions & 3 deletions src/lib/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from './egg.js';
import { AppWorkerLoader } from './loader/index.js';
import Helper from '../app/extend/helper.js';
import { CookieLimitExceedError } from './error/index.js';

const EGG_LOADER = Symbol.for('egg#loader');

Expand Down Expand Up @@ -272,10 +273,10 @@ export class Application extends EggApplicationCore {
* @private
*/
#bindEvents() {
// Browser Cookie Limits: http://browsercookielimits.squawky.net/
// Browser Cookie Limits: http://browsercookielimits.iain.guru/
// https://github.com/eggjs/egg-cookies/blob/58ef4ea497a0eb4dd711d7e9751e56bc5fcee004/src/cookies.ts#L145
this.on('cookieLimitExceed', ({ name, value, ctx }) => {
const err = new Error(`cookie ${name}'s length(${value.length}) exceed the limit(4093)`);
err.name = 'CookieLimitExceedError';
const err = new CookieLimitExceedError(name, value);
ctx.coreLogger.error(err);
});
// expose server to support websocket
Expand Down
12 changes: 12 additions & 0 deletions src/lib/error/CookieLimitExceedError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export class CookieLimitExceedError extends Error {
key: string;
cookie: string;

constructor(key: string, cookie: string) {
super(`cookie ${key}'s length(${cookie.length}) exceed the limit(4093)`);
this.name = this.constructor.name;
this.key = key;
this.cookie = cookie;
Error.captureStackTrace(this, this.constructor);
}
}
1 change: 1 addition & 0 deletions src/lib/error/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './CookieLimitExceedError.js';
9 changes: 9 additions & 0 deletions test/fixtures/apps/demo/config/config.default.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,13 @@ exports.mysql = {
someSecret: null,
};

exports.logger = {
consoleLevel: 'NONE',
coreLogger: {
consoleLevel: 'NONE',
},
concentrateError: 'ignore',
level: 'NONE',
};

exports.tips = 'hello egg';
8 changes: 8 additions & 0 deletions test/fixtures/apps/demo/config/config.unittest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
exports.logger = {
consoleLevel: 'NONE',
coreLogger: {
consoleLevel: 'NONE',
},
concentrateError: 'ignore',
level: 'NONE',
};
6 changes: 6 additions & 0 deletions test/fixtures/apps/keys-missing/config/config.unittest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
exports.logger = {
consoleLevel: 'NONE',
coreLogger: {
consoleLevel: 'NONE',
},
};
107 changes: 54 additions & 53 deletions test/lib/application.test.js → test/lib/application.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
const assert = require('assert');
const mm = require('egg-mock');
const fs = require('fs');
const path = require('path');
const pedding = require('pedding');
const Application = require('../../lib/application');
const utils = require('../utils');

describe('test/lib/application.test.js', () => {
let app;
import { strict as assert } from 'node:assert';
import { mm } from '@eggjs/mock';
import fs from 'node:fs';
import path from 'node:path';
import { scheduler } from 'node:timers/promises';
import { pending } from 'pedding';
import { Application, CookieLimitExceedError } from '../../src/index.js';
import { MockApplication, cluster, createApp, getFilepath, startLocalServer } from '../utils.js';

describe('test/lib/application.test.ts', () => {
let app: MockApplication;

afterEach(mm.restore);

Expand All @@ -16,7 +17,7 @@ describe('test/lib/application.test.js', () => {
assert.throws(() => {
new Application({
baseDir: 1,
});
} as any);
}, /options.baseDir required, and must be a string/);
});

Expand All @@ -25,37 +26,37 @@ describe('test/lib/application.test.js', () => {
new Application({
baseDir: 'not-exist',
});
}, /Directory not-exist not exists/);
}, /not-exist not exists/);
});

it('should throw options.baseDir is not a directory', () => {
assert.throws(() => {
new Application({
baseDir: __filename,
baseDir: getFilepath('custom-egg/index.js'),
});
}, /is not a directory/);
}, /not a directory/);
});
});

describe('app start timeout', function() {
afterEach(() => app.close());
it('should emit `startTimeout` event', function(done) {
app = utils.app('apps/app-start-timeout');
app = createApp('apps/app-start-timeout');
app.once('startTimeout', done);
});
});

describe('app.keys', () => {
it('should throw when config.keys missing on non-local and non-unittest env', async () => {
mm.env('test');
app = utils.app('apps/keys-missing');
app = createApp('apps/keys-missing');
await app.ready();
mm(app.config, 'keys', null);

try {
app.keys;
throw new Error('should not run this');
} catch (err) {
} catch (err: any) {
assert(err.message === 'Please set config.keys first');
}

Expand All @@ -65,14 +66,14 @@ describe('test/lib/application.test.js', () => {

it('should throw when config.keys missing on unittest env', async () => {
mm.env('unittest');
app = utils.app('apps/keys-missing');
app = createApp('apps/keys-missing');
await app.ready();
mm(app.config, 'keys', null);

try {
app.keys;
throw new Error('should not run this');
} catch (err) {
} catch (err: any) {
assert(err.message === 'Please set config.keys first');
}

Expand All @@ -82,14 +83,14 @@ describe('test/lib/application.test.js', () => {

it('should throw when config.keys missing on local env', async () => {
mm.env('local');
app = utils.app('apps/keys-missing');
app = createApp('apps/keys-missing');
await app.ready();
mm(app.config, 'keys', null);

try {
app.keys;
throw new Error('should not run this');
} catch (err) {
} catch (err: any) {
assert(err.message === 'Please set config.keys first');
}

Expand All @@ -99,7 +100,7 @@ describe('test/lib/application.test.js', () => {

it('should use exists keys', async () => {
mm.env('unittest');
app = utils.app('apps/keys-exists');
app = createApp('apps/keys-exists');
await app.ready();

assert(app.keys);
Expand All @@ -111,9 +112,9 @@ describe('test/lib/application.test.js', () => {
});

describe('handle uncaughtException', () => {
let app;
let app: MockApplication;
before(() => {
app = utils.cluster('apps/app-throw');
app = cluster('apps/app-throw');
return app.ready();
});
after(() => app.close());
Expand All @@ -125,16 +126,16 @@ describe('test/lib/application.test.js', () => {
.expect(200);

await scheduler.wait(1100);
const logfile = path.join(utils.getFilepath('apps/app-throw'), 'logs/app-throw/common-error.log');
const logfile = path.join(getFilepath('apps/app-throw'), 'logs/app-throw/common-error.log');
const body = fs.readFileSync(logfile, 'utf8');
assert(body.includes('ReferenceError: a is not defined (uncaughtException throw'));
});
});

describe('handle uncaughtException when error has only a getter', () => {
let app;
let app: MockApplication;
before(() => {
app = utils.cluster('apps/app-throw');
app = cluster('apps/app-throw');
return app.ready();
});
after(() => app.close());
Expand All @@ -146,68 +147,66 @@ describe('test/lib/application.test.js', () => {
.expect(200);

await scheduler.wait(1100);
const logfile = path.join(utils.getFilepath('apps/app-throw'), 'logs/app-throw/common-error.log');
const logfile = path.join(getFilepath('apps/app-throw'), 'logs/app-throw/common-error.log');
const body = fs.readFileSync(logfile, 'utf8');
assert(body.includes('abc (uncaughtException throw 1 times on pid'));
});
});

describe('warn confused configurations', () => {
it('should warn if confused configurations exist', async () => {
const app = utils.app('apps/confused-configuration');
const app = createApp('apps/confused-configuration');
await app.ready();
await scheduler.wait(1000);
const logs = fs.readFileSync(utils.getFilepath('apps/confused-configuration/logs/confused-configuration/confused-configuration-web.log'), 'utf8');
assert(logs.match(/Unexpected config key `bodyparser` exists, Please use `bodyParser` instead\./));
assert(logs.match(/Unexpected config key `notFound` exists, Please use `notfound` instead\./));
assert(logs.match(/Unexpected config key `sitefile` exists, Please use `siteFile` instead\./));
assert(logs.match(/Unexpected config key `middlewares` exists, Please use `middleware` instead\./));
assert(logs.match(/Unexpected config key `httpClient` exists, Please use `httpclient` instead\./));
const logs = fs.readFileSync(getFilepath('apps/confused-configuration/logs/confused-configuration/confused-configuration-web.log'), 'utf8');
assert.match(logs, /Unexpected config key `'bodyparser'` exists, Please use `'bodyParser'` instead\./);
assert.match(logs, /Unexpected config key `'notFound'` exists, Please use `'notfound'` instead\./);
assert.match(logs, /Unexpected config key `'sitefile'` exists, Please use `'siteFile'` instead\./);
assert.match(logs, /Unexpected config key `'middlewares'` exists, Please use `'middleware'` instead\./);
assert.match(logs, /Unexpected config key `'httpClient'` exists, Please use `'httpclient'` instead\./);
});
});

describe('test on apps/demo', () => {
let app;
let app: MockApplication;
before(() => {
app = utils.app('apps/demo');
app = createApp('apps/demo');
return app.ready();
});
after(() => app.close());

describe('application.deprecate', () => {
it('should get deprecate with namespace egg', async () => {
const deprecate = app.deprecate;
assert(deprecate._namespace === 'egg');
assert(deprecate === app.deprecate);
assert.equal(typeof app.deprecate, 'function');
});
});

describe('curl()', () => {
it('should curl success', async () => {
const localServer = await utils.startLocalServer();
const localServer = await startLocalServer();
const res = await app.curl(`${localServer}/foo/app`);
assert(res.status === 200);
assert.equal(res.status, 200);
});
});

describe('env', () => {
it('should return app.config.env', async () => {
it('should return app.config.env', () => {
assert(app.env === app.config.env);
});
});

describe('proxy', () => {
it('should delegate app.config.proxy', async () => {
it('should delegate app.config.proxy', () => {
assert(app.proxy === app.config.proxy);
});
});

describe('inspect && toJSON', () => {
it('should override koa method', function() {
it('should override koa method', () => {
const inspectResult = app.inspect();
const jsonResult = app.toJSON();
assert.deepEqual(inspectResult, jsonResult);
assert(inspectResult.env === app.config.env);
assert.equal(inspectResult.env, app.config.env);
});
});

Expand All @@ -224,21 +223,23 @@ describe('test/lib/application.test.js', () => {
it('should log error', done => {
const ctx = {
coreLogger: {
error(err) {
assert(err.key === 'name');
assert(err.cookie === 'value');
assert(err.name === 'CookieLimitExceedError');
error(err: unknown) {
assert(err instanceof CookieLimitExceedError);
assert.equal(err.key, 'foo');
assert.equal(err.cookie, 'value'.repeat(1000));
assert.equal(err.name, 'CookieLimitExceedError');
assert.equal(err.message, 'cookie foo\'s length(5000) exceed the limit(4093)');
done();
},
},
};
app.emit('cookieLimitExceed', { name: 'name', value: 'value', ctx });
app.emit('cookieLimitExceed', { name: 'foo', value: 'value'.repeat(1000), ctx });
});
});

describe('request and response event', () => {
it('should emit when request success', done => {
done = pedding(done, 3);
done = pending(3, done);
app.once('request', ctx => {
assert(ctx.path === '/class-controller');
done();
Expand All @@ -254,7 +255,7 @@ describe('test/lib/application.test.js', () => {
});

it('should emit when request error', done => {
done = pedding(done, 3);
done = pending(3, done);
app.once('request', ctx => {
assert(ctx.path === '/obj-error');
done();
Expand Down

0 comments on commit d03a004

Please sign in to comment.