]> git.cworth.org Git - obsolete/notmuch-web/blobdiff - node_modules/express/node_modules/connect/lib/middleware/logger.js
Install the "express" node module via npm
[obsolete/notmuch-web] / node_modules / express / node_modules / connect / lib / middleware / logger.js
diff --git a/node_modules/express/node_modules/connect/lib/middleware/logger.js b/node_modules/express/node_modules/connect/lib/middleware/logger.js
new file mode 100644 (file)
index 0000000..f7ff0a1
--- /dev/null
@@ -0,0 +1,169 @@
+
+/*!
+ * Connect - logger
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Log buffer.
+ */
+
+var buf = [];
+
+/**
+ * Default log buffer duration.
+ */
+
+var defaultBufferDuration = 1000;
+
+/**
+ * Log requests with the given `options` or a `format` string.
+ *
+ * Options:
+ *
+ *   - `format`  Format string, see below for tokens
+ *   - `stream`  Output stream, defaults to _stdout_
+ *   - `buffer`  Buffer duration, defaults to 1000ms when _true_
+ *
+ * Tokens:
+ *
+ *   - `:req[header]` ex: `:req[Accept]`
+ *   - `:res[header]` ex: `:res[Content-Length]`
+ *   - `:http-version`
+ *   - `:response-time`
+ *   - `:remote-addr`
+ *   - `:date`
+ *   - `:method`
+ *   - `:url`
+ *   - `:referrer`
+ *   - `:user-agent`
+ *   - `:status`
+ *
+ * @param {String|Function|Object} format or options
+ * @return {Function}
+ * @api public
+ */
+
+module.exports = function logger(options) {
+  if ('object' == typeof options) {
+    options = options || {};
+  } else if (options) {
+    options = { format: options };
+  } else {
+    options = {};
+  }
+
+  var fmt = options.format
+    , stream = options.stream || process.stdout
+    , buffer = options.buffer;
+
+  // buffering support
+  if (buffer) {
+    var realStream = stream
+      , interval = 'number' == typeof buffer
+        ? buffer
+        : defaultBufferDuration;
+
+    // flush interval
+    setInterval(function(){
+      if (buf.length) {
+        realStream.write(buf.join(''), 'ascii');
+        buf.length = 0;
+      }
+    }, interval); 
+
+    // swap the stream
+    stream = {
+      write: function(str){
+        buf.push(str);
+      }
+    };
+  }
+
+  return function logger(req, res, next) {
+    var start = +new Date
+      , statusCode
+      , writeHead = res.writeHead
+      , end = res.end
+      , url = req.originalUrl;
+
+    // mount safety
+    if (req._logging) return next();
+
+    // flag as logging
+    req._logging = true;
+
+    // proxy for statusCode.
+    res.writeHead = function(code, headers){
+      res.writeHead = writeHead;
+      res.writeHead(code, headers);
+      res.__statusCode = statusCode = code;
+      res.__headers = headers || {};
+    };
+
+    // proxy end to output a line to the provided logger.
+    if (fmt) {
+      res.end = function(chunk, encoding) {
+        res.end = end;
+        res.end(chunk, encoding);
+        res.responseTime = +new Date - start;
+        if ('function' == typeof fmt) {
+          var line = fmt(req, res, function(str){ return format(str, req, res); });
+          if (line) stream.write(line + '\n', 'ascii');
+        } else {
+          stream.write(format(fmt, req, res) + '\n', 'ascii');
+        }
+      };
+    } else {
+      res.end = function(chunk, encoding) {
+        var contentLength = (res._headers && res._headers['content-length'])
+          || (res.__headers && res.__headers['Content-Length'])
+          || '-';
+
+        res.end = end;
+        res.end(chunk, encoding);
+
+        stream.write((req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)))
+           + ' - - [' + (new Date).toUTCString() + ']'
+           + ' "' + req.method + ' ' + url
+           + ' HTTP/' + req.httpVersionMajor + '.' + req.httpVersionMinor + '" '
+           + (statusCode || res.statusCode) + ' ' + contentLength
+           + ' "' + (req.headers['referer'] || req.headers['referrer'] || '')
+           + '" "' + (req.headers['user-agent'] || '') + '"\n', 'ascii');
+      };
+    }
+
+    next();
+  };
+};
+
+/**
+ * Return formatted log line.
+ *
+ * @param  {String} str
+ * @param  {IncomingMessage} req
+ * @param  {ServerResponse} res
+ * @return {String}
+ * @api private
+ */
+function format(str, req, res) {
+  return str
+    .replace(':url', req.originalUrl)
+    .replace(':method', req.method)
+    .replace(':status', res.__statusCode || res.statusCode)
+    .replace(':response-time', res.responseTime)
+    .replace(':date', new Date().toUTCString())
+    .replace(':referrer', req.headers['referer'] || req.headers['referrer'] || '')
+    .replace(':http-version', req.httpVersionMajor + '.' + req.httpVersionMinor)
+    .replace(':remote-addr', req.socket && (req.socket.remoteAddress || (req.socket.socket && req.socket.socket.remoteAddress)))
+    .replace(':user-agent', req.headers['user-agent'] || '')
+    .replace(/:req\[([^\]]+)\]/g, function(_, field){ return req.headers[field.toLowerCase()]; })
+    .replace(/:res\[([^\]]+)\]/g, function(_, field){
+      return res._headers
+        ? (res._headers[field.toLowerCase()] || res.__headers[field])
+        : (res.__headers && res.__headers[field]);
+    });
+}