Express middleware는 Java 진영의 Springframework의 interceptor, aop 와 비슷한 성향을 가지고 있습니다.
위 그림을 참고 해보자.
서버로 요청이 들어오면 middleware 는 route / 모든 주소에 대해서 처리하라는 지시를 받습니다. 그 후 특정 url 에 대해서 처리를 한 후 응답을 하게 됩니다.
실제로 log를 확인해 봤습니다.
app object 중 stack
stack:
[ { route: '', handle: [Function: query] },
{ route: '', handle: [Function: expressInit] },
{ route: '', handle: [Function: logger] },
{ route: '', handle: [Function: cookieParser] },
{ route: '', handle: [Function: bodyParser] },
{ route: '', handle: [Function: methodOverride] },
{ route: '', handle: [Function: test] },
{ route: '', handle: [Function: session] },
{ route: '', handle: [Function] },
{ route: '', handle: [Function] },
{ route: '', handle: [Function: router] },
{ route: '', handle: [Function: errorHandler] } ]
app object 중 router
_router:
{ map:
{ get:
[ { path: '/test/test',
method: 'get',
callbacks: [ [Function] ],
keys: [],
regexp: /^\/test\/test\/?$/i },
....
],
post:
[ { path: '/test/test',
method: 'get',
callbacks: [ [Function] ],
keys: [],
regexp: /^\/test\/test\/?$/i },
....
]
}
}
서버로 request가 들어오는 이벤트가 발생할 경우 stack 을 통과하게 됩니다.
개발자가 직접 정의 하는 middleware 는 test 라는 함수이고, 모든 url 처리는 stack 를 통과하고 특정 url은 router 에게 처리를 위임 하게 됩니다. 실제 code를 보도록 하자.
./express/lib/application.js 중 일부 입니다.
/**
* Proxy `connect#use()` to apply settings to
* mounted applications.
*
* @param {String|Function|Server} route
* @param {Function|Server} fn
* @return {app} for chaining
* @api public
*/
app.use = function(route, fn){
var app;
// default route to '/'
if ('string' != typeof route) fn = route, route = '/';
// express app
if (fn.handle && fn.set) app = fn;
// restore .app property on req and res
if (app) {
app.route = route;
fn = function(req, res, next) {
var orig = req.app;
app.handle(req, res, function(err){
req.app = res.app = orig;
req.__proto__ = orig.request;
res.__proto__ = orig.response;
next(err);
});
};
}
connect.proto.use.call(this, route, fn);
// mounted an app
if (app) {
app.parent = this;
app.emit('mount', this);
}
return this;
};
"default route to '/'" 내부적으로 기본 값으로 설정이 되는 것을 확인 할 수 있습니다.
이제 실제 사용법을 알아보도록 하자.
http://expressjs.com/api.html#app.use 공식 홈페이지 Reference 자료 입니다.
두번째 인자로 function 이 사용 됩니다.
위 자료를 참고 하여 Sample Code 작성 해보자.
함수형으로 return 하자.
function test() {
return function test(req, res, next) {
console.log('test');
next();
}
}
next() 는 stack 의 다음 주소로 가라는 함수 입니다. 실제로 next() 를 호출 하지 않는 경우 응답을 하지 못하고 서버에서 멈춰버리게 됩니다.
app.js 설정의 일부 입니다. 실제로 적용 하자.
function setting() {
app.configure(function(){
app.set('port', process.env.PORT);
app.use(express.logger('dev'));
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.methodOverride());
// user middleware
app.use(test());
// session config
app.use(express.session({
secret: config.redis.secret,
store: new RedisStore(config.options),
cookie: config.cookie
}));
app.use(passport.initialize());
app.use(passport.session());
// router
app.use(app.router);
});
}
use 함수 호출 하는 부분을 볼 수 있는데, 해당 행위는 모든 요청에 대해서 처리를 하겠다는 말입니다.
위와 같이 적용 하면 모든 요청에 대해서 test 함수가 호출 되는 것을 확인 할 수 있습니다.
※ 참고 사이트: http://expressjs.com/