118 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict'
 | |
| 
 | |
| /**
 | |
|  * Module dependencies.
 | |
|  */
 | |
| 
 | |
| var express = require('../../');
 | |
| 
 | |
| var app = module.exports = express();
 | |
| 
 | |
| // create an error with .status. we
 | |
| // can then use the property in our
 | |
| // custom error handler (Connect respects this prop as well)
 | |
| 
 | |
| function error(status, msg) {
 | |
|   var err = new Error(msg);
 | |
|   err.status = status;
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| // if we wanted to supply more than JSON, we could
 | |
| // use something similar to the content-negotiation
 | |
| // example.
 | |
| 
 | |
| // here we validate the API key,
 | |
| // by mounting this middleware to /api
 | |
| // meaning only paths prefixed with "/api"
 | |
| // will cause this middleware to be invoked
 | |
| 
 | |
| app.use('/api', function(req, res, next){
 | |
|   var key = req.query['api-key'];
 | |
| 
 | |
|   // key isn't present
 | |
|   if (!key) return next(error(400, 'api key required'));
 | |
| 
 | |
|   // key is invalid
 | |
|   if (apiKeys.indexOf(key) === -1) return next(error(401, 'invalid api key'))
 | |
| 
 | |
|   // all good, store req.key for route access
 | |
|   req.key = key;
 | |
|   next();
 | |
| });
 | |
| 
 | |
| // map of valid api keys, typically mapped to
 | |
| // account info with some sort of database like redis.
 | |
| // api keys do _not_ serve as authentication, merely to
 | |
| // track API usage or help prevent malicious behavior etc.
 | |
| 
 | |
| var apiKeys = ['foo', 'bar', 'baz'];
 | |
| 
 | |
| // these two objects will serve as our faux database
 | |
| 
 | |
| var repos = [
 | |
|   { name: 'express', url: 'https://github.com/expressjs/express' },
 | |
|   { name: 'stylus', url: 'https://github.com/learnboost/stylus' },
 | |
|   { name: 'cluster', url: 'https://github.com/learnboost/cluster' }
 | |
| ];
 | |
| 
 | |
| var users = [
 | |
|   { name: 'tobi' }
 | |
|   , { name: 'loki' }
 | |
|   , { name: 'jane' }
 | |
| ];
 | |
| 
 | |
| var userRepos = {
 | |
|   tobi: [repos[0], repos[1]]
 | |
|   , loki: [repos[1]]
 | |
|   , jane: [repos[2]]
 | |
| };
 | |
| 
 | |
| // we now can assume the api key is valid,
 | |
| // and simply expose the data
 | |
| 
 | |
| // example: http://localhost:3000/api/users/?api-key=foo
 | |
| app.get('/api/users', function (req, res) {
 | |
|   res.send(users);
 | |
| });
 | |
| 
 | |
| // example: http://localhost:3000/api/repos/?api-key=foo
 | |
| app.get('/api/repos', function (req, res) {
 | |
|   res.send(repos);
 | |
| });
 | |
| 
 | |
| // example: http://localhost:3000/api/user/tobi/repos/?api-key=foo
 | |
| app.get('/api/user/:name/repos', function(req, res, next){
 | |
|   var name = req.params.name;
 | |
|   var user = userRepos[name];
 | |
| 
 | |
|   if (user) res.send(user);
 | |
|   else next();
 | |
| });
 | |
| 
 | |
| // middleware with an arity of 4 are considered
 | |
| // error handling middleware. When you next(err)
 | |
| // it will be passed through the defined middleware
 | |
| // in order, but ONLY those with an arity of 4, ignoring
 | |
| // regular middleware.
 | |
| app.use(function(err, req, res, next){
 | |
|   // whatever you want here, feel free to populate
 | |
|   // properties on `err` to treat it differently in here.
 | |
|   res.status(err.status || 500);
 | |
|   res.send({ error: err.message });
 | |
| });
 | |
| 
 | |
| // our custom JSON 404 middleware. Since it's placed last
 | |
| // it will be the last middleware called, if all others
 | |
| // invoke next() and do not respond.
 | |
| app.use(function(req, res){
 | |
|   res.status(404);
 | |
|   res.send({ error: "Sorry, can't find that" })
 | |
| });
 | |
| 
 | |
| /* istanbul ignore next */
 | |
| if (!module.parent) {
 | |
|   app.listen(3000);
 | |
|   console.log('Express started on port 3000');
 | |
| }
 |