arnaucube
arnaucube/raspberryGPIOhtmlserverPublic Self-hosted repository
raspberryGPIOhtmlserver/node_modules/connect/lib/proto.js
node_modules/connect/lib/proto.jsRaw
  1
  2/*!
  3 * Connect - HTTPServer
  4 * Copyright(c) 2010 Sencha Inc.
  5 * Copyright(c) 2011 TJ Holowaychuk
  6 * MIT Licensed
  7 */
  8
  9/**
 10 * Module dependencies.
 11 */
 12
 13var http = require('http')
 14  , utils = require('./utils')
 15  , debug = require('debug')('connect:dispatcher');
 16
 17// prototype
 18
 19var app = module.exports = {};
 20
 21// environment
 22
 23var env = process.env.NODE_ENV || 'development';
 24
 25/**
 26 * Utilize the given middleware `handle` to the given `route`,
 27 * defaulting to _/_. This "route" is the mount-point for the
 28 * middleware, when given a value other than _/_ the middleware
 29 * is only effective when that segment is present in the request's
 30 * pathname.
 31 *
 32 * For example if we were to mount a function at _/admin_, it would
 33 * be invoked on _/admin_, and _/admin/settings_, however it would
 34 * not be invoked for _/_, or _/posts_.
 35 *
 36 * Examples:
 37 *
 38 *      var app = connect();
 39 *      app.use(connect.favicon());
 40 *      app.use(connect.logger());
 41 *      app.use(connect.static(__dirname + '/public'));
 42 *
 43 * If we wanted to prefix static files with _/public_, we could
 44 * "mount" the `static()` middleware:
 45 *
 46 *      app.use('/public', connect.static(__dirname + '/public'));
 47 *
 48 * This api is chainable, so the following is valid:
 49 *
 50 *      connect()
 51 *        .use(connect.favicon())
 52 *        .use(connect.logger())
 53 *        .use(connect.static(__dirname + '/public'))
 54 *        .listen(3000);
 55 *
 56 * @param {String|Function|Server} route, callback or server
 57 * @param {Function|Server} callback or server
 58 * @return {Server} for chaining
 59 * @api public
 60 */
 61
 62app.use = function(route, fn){
 63  // default route to '/'
 64  if ('string' != typeof route) {
 65    fn = route;
 66    route = '/';
 67  }
 68
 69  // wrap sub-apps
 70  if ('function' == typeof fn.handle) {
 71    var server = fn;
 72    fn.route = route;
 73    fn = function(req, res, next){
 74      server.handle(req, res, next);
 75    };
 76  }
 77
 78  // wrap vanilla http.Servers
 79  if (fn instanceof http.Server) {
 80    fn = fn.listeners('request')[0];
 81  }
 82
 83  // strip trailing slash
 84  if ('/' == route[route.length - 1]) {
 85    route = route.slice(0, -1);
 86  }
 87
 88  // add the middleware
 89  debug('use %s %s', route || '/', fn.name || 'anonymous');
 90  this.stack.push({ route: route, handle: fn });
 91
 92  return this;
 93};
 94
 95/**
 96 * Handle server requests, punting them down
 97 * the middleware stack.
 98 *
 99 * @api private
100 */
101
102app.handle = function(req, res, out) {
103  var stack = this.stack
104    , fqdn = ~req.url.indexOf('://')
105    , removed = ''
106    , slashAdded = false
107    , index = 0;
108
109  function next(err) {
110    var layer, path, status, c;
111
112    if (slashAdded) {
113      req.url = req.url.substr(1);
114      slashAdded = false;
115    }
116
117    req.url = removed + req.url;
118    req.originalUrl = req.originalUrl || req.url;
119    removed = '';
120
121    // next callback
122    layer = stack[index++];
123
124    // all done
125    if (!layer || res.headerSent) {
126      // delegate to parent
127      if (out) return out(err);
128
129      // unhandled error
130      if (err) {
131        // default to 500
132        if (res.statusCode < 400) res.statusCode = 500;
133        debug('default %s', res.statusCode);
134
135        // respect err.status
136        if (err.status) res.statusCode = err.status;
137
138        // production gets a basic error message
139        var msg = 'production' == env
140          ? http.STATUS_CODES[res.statusCode]
141          : err.stack || err.toString();
142
143        // log to stderr in a non-test env
144        if ('test' != env) console.error(err.stack || err.toString());
145        if (res.headerSent) return req.socket.destroy();
146        res.setHeader('Content-Type', 'text/plain');
147        res.setHeader('Content-Length', Buffer.byteLength(msg));
148        if ('HEAD' == req.method) return res.end();
149        res.end(msg);
150      } else {
151        debug('default 404');
152        res.statusCode = 404;
153        res.setHeader('Content-Type', 'text/plain');
154        if ('HEAD' == req.method) return res.end();
155        res.end('Cannot ' + req.method + ' ' + utils.escape(req.originalUrl));
156      }
157      return;
158    }
159
160    try {
161      path = utils.parseUrl(req).pathname;
162      if (undefined == path) path = '/';
163
164      // skip this layer if the route doesn't match.
165      if (0 != path.toLowerCase().indexOf(layer.route.toLowerCase())) return next(err);
166
167      c = path[layer.route.length];
168      if (c && '/' != c && '.' != c) return next(err);
169
170      // Call the layer handler
171      // Trim off the part of the url that matches the route
172      removed = layer.route;
173      req.url = req.url.substr(removed.length);
174
175      // Ensure leading slash
176      if (!fqdn && '/' != req.url[0]) {
177        req.url = '/' + req.url;
178        slashAdded = true;
179      }
180
181      debug('%s', layer.handle.name || 'anonymous');
182      var arity = layer.handle.length;
183      if (err) {
184        if (arity === 4) {
185          layer.handle(err, req, res, next);
186        } else {
187          next(err);
188        }
189      } else if (arity < 4) {
190        layer.handle(req, res, next);
191      } else {
192        next();
193      }
194    } catch (e) {
195      next(e);
196    }
197  }
198  next();
199};
200
201/**
202 * Listen for connections.
203 *
204 * This method takes the same arguments
205 * as node's `http.Server#listen()`.  
206 *
207 * HTTP and HTTPS:
208 *
209 * If you run your application both as HTTP
210 * and HTTPS you may wrap them individually,
211 * since your Connect "server" is really just
212 * a JavaScript `Function`.
213 *
214 *      var connect = require('connect')
215 *        , http = require('http')
216 *        , https = require('https');
217 *      
218 *      var app = connect();
219 *      
220 *      http.createServer(app).listen(80);
221 *      https.createServer(options, app).listen(443);
222 *
223 * @return {http.Server}
224 * @api public
225 */
226
227app.listen = function(){
228  var server = http.createServer(this);
229  return server.listen.apply(server, arguments);
230};