forked from expressjs/expressjs.com
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathguide.html
238 lines (231 loc) · 12.4 KB
/
guide.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<!DOCTYPE html><html><head><title>Express - guide</title><link rel="stylesheet" href="style.css"><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&subset=latin,latin-ext"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script><script src="app.js"></script><script src="retina.js"></script></head><body class="inner"><div class="bar"></div><section id="content"><header><section id="logo"><span class="express">express<em>3.0.0</em></span><span class="description">
web application framework for <a href="http://nodejs.org">node </a></span></section><nav class="clearfix"><a href="/" class=""> Home</a><a href="/api.html" class=""> API Reference</a><a href="/guide.html" class="active"> Guide</a><a href="/applications.html" class=""> Applications</a><a href="/community.html" class=""> Community</a><a href="/faq.html" class=""> FAQ</a></nav></header><ul id="menu"><li><ul><li><a href="#intro">Getting started</a></li><li><a href="#executable">express(1) executable</a></li><li><a href="#error-handling">Error handling</a></li><li><a href="#users-online">Users online count</a></li><li><a href="#proxies">Express behind proxies</a></li></ul></li></ul><section><h3 id="intro">Getting started</h3><p>With node installed (<a href="http://nodejs.org/download">download</a>),
get your first application started by creating a directory somewhere
on your machine:
</p><pre class="js"><code>$ mkdir hello-world
</code></pre><p>In this same directory you'll be defining the application "package", which
are no different than any other node package. You'll need a package.json
file in the directory, with express defined as a dependency. You may use
<code>npm info express version</code> to fetch the latest version, it's
preferred that you do this instead of "3.x" below to prevent any future
surprises.
</p><pre class="js"><code>{
"name": "hello-world",
"description": "hello world test app",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "3.x"
}
}
</code></pre><p>Now that you have a package.json file in this directory you can use
<code>npm(1)</code> to install the dependencies, in this case just
Express:
</p><pre class="js"><code>$ npm install
</code></pre><p>Once npm finishes you'll have a localized Express 3.x dependency in
the ./node_modules directory. You may verify this with <code>npm ls</code>
as shown in the following snippet displaying a tree of Express and its
own dependencies.
</p><pre class="js"><code>$ npm ls
[email protected] /private/tmp
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └── [email protected]
│ └── [email protected]
</code></pre><p>Now to create the application itself! Create a file named app.js or server.js,
whichever you prefer, require express and then create a new application with <code>express()</code>:
</p><pre class="js"><code>var express = require('express');
var app = express();
</code></pre><p>With the new application instance you can start defining routes via <code>app.VERB()</code>,
in this case "GET /" responding with the "Hello World" string. The <code>req</code> and
<code>res</code> are the exact same objects that node provides to you, thus you may invoke
<code>res.pipe()</code>, <code>req.on('data', callback)</code> and anything else you
would do without Express involved.
</p><pre class="js"><code>app.get('/hello.txt', function(req, res){
var body = 'Hello World';
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Length', body.length);
res.end(body);
});
</code></pre><p>Express augments these objects providing you with higher level
methods such as <code>res.send()</code>, which among other things
adds the Content-Length for you:
</p><pre class="js"><code>app.get('/hello.txt', function(req, res){
res.send('Hello World');
});
</code></pre><p>Now to bind and listen for connections invoke the <code>app.listen()</code> method,
accepting the same arguments as node's <a href="http://nodejs.org/api/net.html#net_server_listen_port_host_backlog_listeninglistener">net.Server#listen()</a>:
</p><pre class="js"><code>app.listen(3000);
console.log('Listening on port 3000');</code></pre></section><section><h3 id="executable">Using express(1) to generate an app</h3><p>Express is bundled with an executable, aptly named <code>express(1)</code>.
If you install express globally with npm you'll have it available from anywhere
on your machine:
</p><pre class="js"><code>$ npm install -g express
</code></pre><p>This tool provides a simple way to get an application skeleton going,
but has limited scope, for example it supports only a few template engines,
whereas Express itself supports virtually any template engine built for node.
Be sure to check out the <code>--help</code>:
</p><pre class="js"><code>Usage: express [options]
Options:
-h, --help output usage information
-V, --version output the version number
-s, --sessions add session support
-e, --ejs add ejs engine support (defaults to jade)
-J, --jshtml add jshtml engine support (defaults to jade)
-H, --hogan add hogan.js engine support
-c, --css <engine> add stylesheet <engine> support (less|stylus) (defaults to plain css)
-f, --force force on non-empty directory</code></pre><p>If you want to generate an application with EJS, Stylus, and session
support you would simply execute:
</p><pre class="js"><code>$ express --sessions --css stylus --ejs 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.ejs
install dependencies:
$ cd myapp && npm install
run the app:
$ node app
</code></pre><p>Like any other node application, you must then install the dependencies:
</p><pre class="js"><code>$ cd myapp
$ npm install
</code></pre><p>Then fire it up!
</p><pre class="js"><code>$ node app
</code></pre><p>That's all you need to get a simple application up and running. Keep in mind
that Express is not bound to any specific directory structure, these are simply
a baseline for you to work from. For application structure alternatives be
sure to view the <a href="https://github.com/visionmedia/express/tree/master/examples">examples</a>
found in the github repo.</p></section><section><h3 id="error-handling">Error handling</h3><p>Error-handling middleware are defined just like regular middleware,
however must be defined with an arity of 4, that is the signature
<code>(err, req, res, next)</code>:
</p><pre class="js"><code>app.use(function(err, req, res, next){
console.error(err.stack);
res.send(500, 'Something broke!');
});
</code></pre><p>Though not mandatory error-handling middleware are typically defined
very last, below any other <code>app.use()</code> calls as shown here:
</p><pre class="js"><code>app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(function(err, req, res, next){
// logic
});
</code></pre><p>Responses from within these middleware are completely arbitrary. You may
wish to respond with an HTML error page, a simple message, a JSON string,
or anything else you prefer.
</p><p>For organizational, and higher-level framework purposes you may define
several of these error-handling middleware, much like you would with
regular middleware. For example suppose you wanted to define an error-handler
for requests made via XHR, and those without, you might do:
</p><pre class="js"><code>app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);
</code></pre><p>Where the more generic <code>logErrors</code> may write request and
error information to stderr, loggly, or similar services:
</p><pre class="js"><code>function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}
</code></pre><p>Where <code>clientErrorHandler</code> is defined as the following, note
that the error is explicitly passed along to the next.
</p><pre class="js"><code>function clientErrorHandler(err, req, res, next) {
if (req.xhr) {
res.send(500, { error: 'Something blew up!' });
} else {
next(err);
}
}
</code></pre><p>The following <code>errorHandler</code> "catch-all" implementation may be defined as:
</p><pre class="js"><code>function errorHandler(err, req, res, next) {
res.status(500);
res.render('error', { error: err });
}</code></pre></section><section><h3 id="users-online">Users online count</h3><p>This section details a full (small) application that tracks a users online
count using <a href="http://redis.io">Redis</a>. First up you'll need to
create a package.json file containing two dependencies, one for the redis
client, another for Express itself. Also make sure you have redis installed
and running via <code>$ redis-server</code>.
</p><pre class="js"><code>{
"name": "app",
"version": "0.0.1",
"dependencies": {
"express": "3.x",
"redis": "*"
}
}
</code></pre><p>Next you'll need to create an app, and a connection to redis:
</p><pre class="js"><code>var express = require('express');
var redis = require('redis');
var db = redis.createClient();
var app = express();
</code></pre><p>Next up is the middleware for tracking online users. Here we'll
use sorted sets so that we can query redis for the users
online within the last N milliseconds. We do this by passing
a timestamp as the member's "score". Note that here we're using
the User-Agent string in place of what would normally be a user id.
</p><pre class="js"><code>app.use(function(req, res, next){
var ua = req.headers['user-agent'];
db.zadd('online', Date.now(), ua, next);
});
</code></pre><p>This next middleware is for fetching the users online
in the last minute using <strong>zrevrangebyscore</strong>
to fetch with a positive infinite max value so that we're
always getting the most recent users, capped with a minimum score
of the current timestamp minus 60,000 milliseconds.
</p><pre class="js"><code>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();
});
});
</code></pre><p>Then finally we use it, and bind to a port! That's
all there is to it, visit the app in a few browsers
and you'll see the count increase.
</p><pre class="js"><code>app.get('/', function(req, res){
res.send(req.online.length + ' users online');
});
app.listen(3000);</code></pre></section><section><h3 id="proxies">Express behind proxies</h3><p>Using Express behind a reverse proxy such as Varnish or Nginx
is trivial, however it does require configuration. By enabling the "trust proxy" setting via
<code>app.enable('trust proxy')</code>, Express will have knowledge that
it's sitting behind a proxy and that the <code>X-Forwarded-*</code> header
fields may be trusted, which otherwise may be easily spoofed.
</p><p>Enabling this setting has several subtle effects. The first of which is
that <code>X-Forwarded-Proto</code> may be set by the reverse proxy to
tell the app that it is https or simply http. This value is reflected
by <a href="/api#req.protocol">req.protocol</a>.
</p><p>The second change this makes is the <a href="/api#req.ip">req.ip</a>
and <a href="/api#req.ips">req.ips</a> values will be populated with
<code>X-Forwarded-For</code>'s list of addresses. </p></section></section><script>var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-25235225-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script><a id="top" href="#"><img src="images/arrow.png"></a><footer><div id="footer-content">© 2012 TJ Holowaychuk. All rights reserved.</div></footer></body></html>