Notice
Recent Posts
Recent Comments
Dharma
[Express] Node.js 의 웹프레임워크 익스프레스에서의 미들웨어 만들기 본문
Express (Node.js의 웹 프레임 워크) 에서의 Middleware 개념은 쉽게 설명하자면 Java 에서의 Filter 와 비슷한 개념입니다. 자주 쓰이고 통념적으로 쓰이는 행위들을 미리 걸러주는 역할을 한다고 볼 수 있습니다.
예로 들면 express 가 내부적으로 쓰고 있는 formidable 은 HTTP의 request 를 정리하는데 탁월합니다. 그러나 개발자가 매번 formidable 을 불러서 정리하는 것이 번거로울 수가 있기 때문에 이를 middleware 로 만들어서
app.use(express.bodyParser());
이런식으로 선언만 해두면 사용이 되는 것입니다. (내부적으로 formidable 이 쓰이고 있음. )
이런 미들웨어를 만드는 법이 찾아보진 않았지만 예제가 많지는 않습니다. (너무 쉬워서 그럴 수도..)
다행히 위 링크에 가면 fineuploader 가 올리는 xhr 방식의 asynchronous 데이타 전송을 잡아채서 req.files 에 정리하는 부분을 미들웨어로 구현한 소스가 있습니다. 비록 옛날 소스이긴 하지만 (요즘 express 가 너무 많이 발전을 한 관계로..) 어떻게 미들웨어를 만드는지 참조하시면 좋을 듯합니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*jslint node: true */ | |
"use strict"; | |
var formidable = require('formidable'), | |
qs = require('qs'); | |
function mime(req) { | |
var str = req.headers['content-type'] || ''; | |
return str.split(';')[0]; | |
} | |
/** | |
* octetStream: mostly nicked from connect's multipart.js | |
* | |
* Parse application/octet-stream request bodies, | |
* providing the parsed object as `req.body` | |
* and `req.files`. | |
* | |
* Configuration: | |
* | |
* The options passed are merged with [formidable](https://github.com/felixge/node-formidable)'s | |
* `IncomingForm` object, allowing you to configure the upload directory, | |
* size limits, etc. For example if you wish to change the upload dir do the following. | |
* | |
* app.use(fineuploaderExpressMiddleware({ uploadDir: path })); | |
* | |
* @param {Object} options | |
* @return {Function} | |
* @api public | |
*/ | |
exports = module.exports = function(options){ | |
options = options || {}; | |
return function octetStream(req, res, next) { | |
if (req._body) return next(); | |
req.body = req.body || {}; | |
req.files = req.files || {}; | |
// ignore GET | |
if ('GET' == req.method || 'HEAD' == req.method) return next(); | |
// check Content-Type | |
if ('application/octet-stream' !== mime(req)) return next(); | |
// flag as parsed | |
req._body = true; | |
// parse | |
var form = new formidable.IncomingForm(), | |
files = {}, | |
done; | |
Object.keys(options).forEach(function(key){ | |
form[key] = options[key]; | |
}); | |
function ondata(name, val, data){ | |
if (Array.isArray(data[name])) { | |
data[name].push(val); | |
} else if (data[name]) { | |
data[name] = [data[name], val]; | |
} else { | |
data[name] = val; | |
} | |
} | |
form.on('file', function(name, val){ | |
ondata(name, val, files); | |
}); | |
form.on('error', function(err){ | |
if (!options.defer) { | |
err.status = 400; | |
next(err); | |
} | |
done = true; | |
}); | |
form.on('end', function(){ | |
if (done) return; | |
try { | |
req.body = null; | |
req.files = qs.parse(files); | |
if (!options.defer) next(); | |
} catch (err) { | |
form.emit('error', err); | |
} | |
}); | |
form.parse(req); | |
if (options.defer) { | |
req.form = form; | |
next(); | |
} | |
}; | |
}; |
글을 퍼올 수가 없어서 어쩔 수 없이 제 gist 에 올렸습니다. 원문은 위에 링크되어 있는 주소로 가면 나옵니다. (동작하는지에 대한 보장은 해 드릴 수 없습니다)
(req, res, next) 로 이루어진 전형적인 미들웨어형 함수 선언이 보입니다. 위 사이트를 가면 어떻게 npm 패키지를 만드는 지에 관한 방법도 감을 잡으실 수가 있을 것입니다.