After installing node (download), create a directory on your machine and start your first application.
$ mkdir hello-world
In this directory you will define application "packages", which are no different from any other node packages. The json file in the file directory clearly defines a dependency. You can use the npm command to get the latest version of express, whichever you prefer, rather than installing a version other than "3.x" to prevent any unknown surprises.
{ "name": "hello-world", "description": "hello world test app", "version": "0.0.1", "private": true, "dependencies": { "express": "3.x" } }
Now, you have a package. json file in this directory you can use npm(1) to install this dependency, in this case just type:
$ npm install
Once npm is complete, you will have an Express 3.x dependency in the /node_modules directory. You can verify this with npm ls, as the following snippet shows the Express tree and its own dependencies.
$ npm ls hello-world@0.0.1 /private/tmp └─┬ express@3.0.0beta7 ├── commander@0.6.1 ├─┬ connect@2.3.9 │ ├── bytes@0.1.0 │ ├── cookie@0.0.4 │ ├── crc@0.2.0 │ ├── formidable@1.0.11 │ └── qs@0.4.2 ├── cookie@0.0.3 ├── debug@0.7.0 ├── fresh@0.1.0 ├── methods@0.0.1 ├── mkdirp@0.3.3 ├── range-parser@0.0.4 ├─┬ response-send@0.0.1 │ └── crc@0.2.0 └─┬ send@0.0.3 └── mime@1.2.6
Now to create the application itself! Create a file called app.js or server.js, whichever you prefer, import express, and then use express() to create a new application:
var express = require('express'); var app = express();
New application instances can start defining routes via app.VERB(), in this case responding to a "GET/" request with the "Hello World" string. req and res are the exact same node objects provided to you, so you might call res.pipe(), req.on('data', callback) and other things you would do that have nothing to do with Express.
Express enhances these objects to provide you with higher level interfaces such as res.send(), in addition to adding content length for you:
app.get('/hello.txt', function(req, res){ res.send('Hello World'); });
Now call the app.listen() method for the connection to bind and listen, accepting the same parameters as the node's net.Server #listen():
var server = app.listen(3000, function() { console.log('Listening on port %d', server.address().port); });
Use express(1) to generate applications
The Express team maintains a convenient project generator named express-generator(1). If you install express-generator globally using npm, you can access it from anywhere on your computer:
$ npm install -g express-generator
This tool provides an easy way to get an application framework, but is limited in scope, for example, it only supports a few template engines, while Express itself actually supports building any website framework template for node. Can be viewed through help:
Usage: express [options] Options: -h, --help output usage information -V, --version output the version number -e, --ejs add ejs engine support (defaults to jade) -H, --hogan add hogan.js engine support -c, --css add stylesheet support (less|stylus|compass) (defaults to plain css) -f, --force force on non-empty directory
If you want to generate an application that supports any situation you just need to simply execute::
$ express --css stylus myapp create : myapp create : myapp/package.json create : myapp/app.js create : myapp/public create : myapp/public/javascripts create : myapp/public/images create : myapp/public/stylesheets create : myapp/public/stylesheets/style.styl create : myapp/routes create : myapp/routes/index.js create : myapp/views create : myapp/views/index.jade create : myapp/views/layout.jade install dependencies: $ cd myapp && npm install run the app: $ DEBUG=myapp node app
Like any other node application, you must install the following dependencies:
Then let’s get started.
$ npm start
That's all you need to get a simple app up and running. Remember, Express is not tied to any specific directory structure, these are just to give you a guide. Choices of application structures can be viewed in the examples in the github repository.
Error handling
Error handling middleware is defined just like ordinary middleware, but it must define the number of 4 parameters. This is the function signature (err, req, res, next):
app.use(function(err, req, res, next){ console.error(err.stack); res.send(500, 'Something broke!'); });
Although mandatory error handling middleware is usually not defined at the end, after other app.use(), its call is as follows:
var bodyParser = require('body-parser'); var methodOverride = require('method-override'); app.use(bodyParser()); app.use(methodOverride()); app.use(app.router); app.use(function(err, req, res, next){ // logic });
Responses in these middlewares are completely arbitrary. You may wish to respond with an HTML error page, a simple message, a JSON string, or any other response you like.
To build an organized and higher-level framework, you can define several of these error handling middlewares, just like you would define ordinary middleware. For example, suppose you want to define an error handler for XHR requests. In addition to these, you might do the following:
var bodyParser = require('body-parser'); var methodOverride = require('method-override'); app.use(bodyParser()); app.use(methodOverride()); app.use(app.router); app.use(logErrors); app.use(clientErrorHandler); app.use(errorHandler);
In more general logErrors you can write request and error messages to stderr, loggly, or similar services:
function logErrors(err, req, res, next) { console.error(err.stack); next(err); }
The definition of clientErrorHandler is as follows, note that this error will be passed to the next one explicitly.
function clientErrorHandler(err, req, res, next) { if (req.xhr) { res.send(500, { error: 'Something blew up!' }); } else { next(err); } }
The following "all-round" implementation of errorHandler can be defined as:
function errorHandler(err, req, res, next) { res.status(500); res.render('error', { error: err }); }
User online count
This section explains in detail a (small) application that uses Redis to track the number of online users. First create a package. The json file contains two attachments, one for the redis client and the other for Express itself. Also make sure you have redis wrapped and running via $redis-server.
{ "name": "app", "version": "0.0.1", "dependencies": { "express": "3.x", "redis": "*" } }
Next, you need to create an application and a connection to redis:
var express = require('express'); var redis = require('redis'); var db = redis.createClient(); var app = express();
The next middleware tracks online users. Here we will use a sorted set, so that we can query online users through redis, which only takes N milliseconds. We use timestamps as an "online standard" for members. Note that here we use the user-agent string instead of the usual user id.
app.use(function(req, res, next){ var ua = req.headers['user-agent']; db.zadd('online', Date.now(), ua, next); });
The next middleware is to use zrevrangebyscore to get the maximum number of online users at the last moment. We always get the most recently online user, and his upper limit is the current timestamp minus 60000 milliseconds.
app.use(function(req, res, next){ var min = 60 * 1000; var ago = Date.now() - min; db.zrevrangebyscore('online', '+inf', ago, function(err, users){ if (err) return next(err); req.online = users; next(); }); });
最后,我们通过一个url使用它,并绑定到一个端口!这就完了,在一个新浏览器访问这个应用程序,您会看到在线人数增加。
app.get('/', function(req, res){ res.send(req.online.length + ' users online'); }); app.listen(3000);
Expree的反向代理
在反向代理背后使用Expree,如Varnish 或Nginx是微不足道的,然而它需要配置。通过启用“信任代理”设置app.enable(“trust proxy”),Express有一些反向代理的技巧,X-Forwarded - *头字段可能是可信的,否则他们可能很容易被欺骗。
启用该设置有一些微妙的影响。第一个是X-Forwarded-Proto可能被反向代理设定,告诉app那是https或者只是简单的http。这个值由req.protocol反射。
第二个变化是req.ip和req.ips值将填充X-Forwarded-For地址的列表。
调试Express
Express内部使用调试模块记录路径匹配和应用程序模式的信息。要看到这条信息,只要简单设置调试环境变量为express:*,当启动应用程序后,你将在控制台看以调试信息。
$ DEBUG=express:* node ./bin/www
运行这个hello world示例将打印以下内容:
express:application booting in development mode +0ms express:router defined get /hello.txt +0ms express:router defined get /hello.txt +1ms
另外, 表达可执行(生成器)生成的程序也使用调试模块,默认作用域是my-application调试命名空间。
你可以用以下命令启用这些调试语句
$ DEBUG=my-application node ./bin/www
关于调试的更多信息,请参见调试 指南