What Is New in Express 3
| Category | Feature |
|---|---|
| New Feature | app.head() support |
| New Feature | app.locals and app.locals(obj) |
| New Feature | app.render and app.engine for view handling |
| Improvement | trust proxy setting for X-Forwarded-Proto and X-Forwarded-For |
| Improvement | json spaces and json replacer settings for res.json() |
| New Feature | Request helpers: req.path, req.protocol, req.get, req.accepts*, req.accepted*, req.signedCookies, req.stale/fresh, req.ips, req.ip, req.range |
| New Feature | Response helpers: res.get, res.set, res.type, res.format, res.locals, res.redirect relative, res.links, res.jsonp, JSON and signed cookie support |
| New Feature | express.application, express.request, express.response prototypes |
How does Express 3 handle proxy headers and HTTPS detection?
Express 3 adds a trust proxy setting that makes req.protocol and res.redirect respect the X-Forwarded-Proto and X-Forwarded-For headers.
app.set('trust proxy', true);
app.get('/', function (req, res) {
// req.protocol will be 'https' if X-Forwarded-Proto is 'https'
res.send('Protocol: ' + req.protocol);
});
When the flag is on, req.ip also falls back to the first entry in req.ips, giving you the real client address behind a load balancer.
What new request helpers does Express 3 provide?
Express 3 ships with a richer req object that covers routing, content negotiation, caching and range parsing out of the box.
| Helper | What it gives you |
|---|---|
| req.path | the URL pathname without query string |
| req.protocol | "http" or "https", respects trust proxy |
| req.get(field) | shortcut for req.headers[field.toLowerCase()] |
| req.accepts(...types) | returns the best match based on the Accept header |
| req.accepted | sorted array of accepted media types |
| req.acceptsCharset(...) | negotiates character sets |
| req.acceptsLanguage(...) | negotiates languages |
| req.signedCookies | object of cookies that were signed with the secret |
| req.stale / req.fresh | cache-validation helpers based on ETag/Last-Modified |
| req.ips & req.ip | array of forwarded IPs and the first client IP |
| req.range(size) | parses the Range header into start/end pairs |
These helpers cut down on boilerplate; you no longer need external modules for basic content-negotiation or IP extraction.
How can I simplify response handling with Express 3's new methods?
Express 3 adds a suite of res utilities that let you set headers, negotiate content, and manage cookies without reaching for third-party libraries.
app.get('/data', function (req, res) {
res.type('json');
res.format({
json: function () { res.json({ ok: true }); },
html: function () { res.send('<h1>OK</h1>'); }
});
});
Use res.locals to stash view data, res.links to emit RFC-5988 Link headers, and res.jsonp for explicit JSONP callbacks. Cookie handling now accepts objects directly, and signed cookies are a one-liner with { signed: true }.
Why should I use app.locals and res.locals in Express 3?
app.locals and res.locals give you a clean, template-friendly namespace that lives outside the request cycle.
Set global values once on the app:
app.locals.siteName = 'Acme Corp';
Then add request-specific data in a route:
app.get('/', function (req, res) {
res.locals.user = req.user;
res.render('home');
});
This avoids mutating req and keeps your view layer decoupled from middleware concerns.
Common Questions
Does enabling trust proxy affect how req.ip is calculated?
Yes, with trust proxy on, req.ip returns the first address in the X-Forwarded-For header instead of the direct socket address.
How do I set multiple response headers at once?
You can pass an object to res.set, e.g., res.set({ 'Cache-Control': 'no-cache', 'X-Powered-By': 'Express' }).
Can I render a view without attaching a route handler?
Yes, app.render lets you invoke a view directly from any part of your code, returning the HTML via a callback.
What is the difference between res.type and res.contentType?
res.type is an alias for res.contentType; both set the Content-Type header based on the given mime or extension.
How do I send pretty-printed JSON in production?
Set app.set('json spaces', 2) to have res.json format its output with two-space indentation.