Dieses Repository beinhaltet HTML- und Javascript Code zur einer NotizenWebApp auf Basis von Web Storage. Zudem sind Mocha/Chai Tests im Browser enthalten. https://meinenotizen.netlify.app/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /*!
  2. * morgan
  3. * Copyright(c) 2010 Sencha Inc.
  4. * Copyright(c) 2011 TJ Holowaychuk
  5. * Copyright(c) 2014 Jonathan Ong
  6. * Copyright(c) 2014-2017 Douglas Christopher Wilson
  7. * MIT Licensed
  8. */
  9. 'use strict'
  10. /**
  11. * Module exports.
  12. * @public
  13. */
  14. module.exports = morgan
  15. module.exports.compile = compile
  16. module.exports.format = format
  17. module.exports.token = token
  18. /**
  19. * Module dependencies.
  20. * @private
  21. */
  22. var auth = require('basic-auth')
  23. var debug = require('debug')('morgan')
  24. var deprecate = require('depd')('morgan')
  25. var onFinished = require('on-finished')
  26. var onHeaders = require('on-headers')
  27. /**
  28. * Array of CLF month names.
  29. * @private
  30. */
  31. var CLF_MONTH = [
  32. 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
  33. 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
  34. ]
  35. /**
  36. * Default log buffer duration.
  37. * @private
  38. */
  39. var DEFAULT_BUFFER_DURATION = 1000
  40. /**
  41. * Create a logger middleware.
  42. *
  43. * @public
  44. * @param {String|Function} format
  45. * @param {Object} [options]
  46. * @return {Function} middleware
  47. */
  48. function morgan (format, options) {
  49. var fmt = format
  50. var opts = options || {}
  51. if (format && typeof format === 'object') {
  52. opts = format
  53. fmt = opts.format || 'default'
  54. // smart deprecation message
  55. deprecate('morgan(options): use morgan(' + (typeof fmt === 'string' ? JSON.stringify(fmt) : 'format') + ', options) instead')
  56. }
  57. if (fmt === undefined) {
  58. deprecate('undefined format: specify a format')
  59. }
  60. // output on request instead of response
  61. var immediate = opts.immediate
  62. // check if log entry should be skipped
  63. var skip = opts.skip || false
  64. // format function
  65. var formatLine = typeof fmt !== 'function'
  66. ? getFormatFunction(fmt)
  67. : fmt
  68. // stream
  69. var buffer = opts.buffer
  70. var stream = opts.stream || process.stdout
  71. // buffering support
  72. if (buffer) {
  73. deprecate('buffer option')
  74. // flush interval
  75. var interval = typeof buffer !== 'number'
  76. ? DEFAULT_BUFFER_DURATION
  77. : buffer
  78. // swap the stream
  79. stream = createBufferStream(stream, interval)
  80. }
  81. return function logger (req, res, next) {
  82. // request data
  83. req._startAt = undefined
  84. req._startTime = undefined
  85. req._remoteAddress = getip(req)
  86. // response data
  87. res._startAt = undefined
  88. res._startTime = undefined
  89. // record request start
  90. recordStartTime.call(req)
  91. function logRequest () {
  92. if (skip !== false && skip(req, res)) {
  93. debug('skip request')
  94. return
  95. }
  96. var line = formatLine(morgan, req, res)
  97. if (line == null) {
  98. debug('skip line')
  99. return
  100. }
  101. debug('log request')
  102. stream.write(line + '\n')
  103. };
  104. if (immediate) {
  105. // immediate log
  106. logRequest()
  107. } else {
  108. // record response start
  109. onHeaders(res, recordStartTime)
  110. // log when response finished
  111. onFinished(res, logRequest)
  112. }
  113. next()
  114. }
  115. }
  116. /**
  117. * Apache combined log format.
  118. */
  119. morgan.format('combined', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"')
  120. /**
  121. * Apache common log format.
  122. */
  123. morgan.format('common', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]')
  124. /**
  125. * Default format.
  126. */
  127. morgan.format('default', ':remote-addr - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"')
  128. deprecate.property(morgan, 'default', 'default format: use combined format')
  129. /**
  130. * Short format.
  131. */
  132. morgan.format('short', ':remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms')
  133. /**
  134. * Tiny format.
  135. */
  136. morgan.format('tiny', ':method :url :status :res[content-length] - :response-time ms')
  137. /**
  138. * dev (colored)
  139. */
  140. morgan.format('dev', function developmentFormatLine (tokens, req, res) {
  141. // get the status code if response written
  142. var status = headersSent(res)
  143. ? res.statusCode
  144. : undefined
  145. // get status color
  146. var color = status >= 500 ? 31 // red
  147. : status >= 400 ? 33 // yellow
  148. : status >= 300 ? 36 // cyan
  149. : status >= 200 ? 32 // green
  150. : 0 // no color
  151. // get colored function
  152. var fn = developmentFormatLine[color]
  153. if (!fn) {
  154. // compile
  155. fn = developmentFormatLine[color] = compile('\x1b[0m:method :url \x1b[' +
  156. color + 'm:status\x1b[0m :response-time ms - :res[content-length]\x1b[0m')
  157. }
  158. return fn(tokens, req, res)
  159. })
  160. /**
  161. * request url
  162. */
  163. morgan.token('url', function getUrlToken (req) {
  164. return req.originalUrl || req.url
  165. })
  166. /**
  167. * request method
  168. */
  169. morgan.token('method', function getMethodToken (req) {
  170. return req.method
  171. })
  172. /**
  173. * response time in milliseconds
  174. */
  175. morgan.token('response-time', function getResponseTimeToken (req, res, digits) {
  176. if (!req._startAt || !res._startAt) {
  177. // missing request and/or response start time
  178. return
  179. }
  180. // calculate diff
  181. var ms = (res._startAt[0] - req._startAt[0]) * 1e3 +
  182. (res._startAt[1] - req._startAt[1]) * 1e-6
  183. // return truncated value
  184. return ms.toFixed(digits === undefined ? 3 : digits)
  185. })
  186. /**
  187. * total time in milliseconds
  188. */
  189. morgan.token('total-time', function getTotalTimeToken (req, res, digits) {
  190. if (!req._startAt || !res._startAt) {
  191. // missing request and/or response start time
  192. return
  193. }
  194. // time elapsed from request start
  195. var elapsed = process.hrtime(req._startAt)
  196. // cover to milliseconds
  197. var ms = (elapsed[0] * 1e3) + (elapsed[1] * 1e-6)
  198. // return truncated value
  199. return ms.toFixed(digits === undefined ? 3 : digits)
  200. })
  201. /**
  202. * current date
  203. */
  204. morgan.token('date', function getDateToken (req, res, format) {
  205. var date = new Date()
  206. switch (format || 'web') {
  207. case 'clf':
  208. return clfdate(date)
  209. case 'iso':
  210. return date.toISOString()
  211. case 'web':
  212. return date.toUTCString()
  213. }
  214. })
  215. /**
  216. * response status code
  217. */
  218. morgan.token('status', function getStatusToken (req, res) {
  219. return headersSent(res)
  220. ? String(res.statusCode)
  221. : undefined
  222. })
  223. /**
  224. * normalized referrer
  225. */
  226. morgan.token('referrer', function getReferrerToken (req) {
  227. return req.headers.referer || req.headers.referrer
  228. })
  229. /**
  230. * remote address
  231. */
  232. morgan.token('remote-addr', getip)
  233. /**
  234. * remote user
  235. */
  236. morgan.token('remote-user', function getRemoteUserToken (req) {
  237. // parse basic credentials
  238. var credentials = auth(req)
  239. // return username
  240. return credentials
  241. ? credentials.name
  242. : undefined
  243. })
  244. /**
  245. * HTTP version
  246. */
  247. morgan.token('http-version', function getHttpVersionToken (req) {
  248. return req.httpVersionMajor + '.' + req.httpVersionMinor
  249. })
  250. /**
  251. * UA string
  252. */
  253. morgan.token('user-agent', function getUserAgentToken (req) {
  254. return req.headers['user-agent']
  255. })
  256. /**
  257. * request header
  258. */
  259. morgan.token('req', function getRequestToken (req, res, field) {
  260. // get header
  261. var header = req.headers[field.toLowerCase()]
  262. return Array.isArray(header)
  263. ? header.join(', ')
  264. : header
  265. })
  266. /**
  267. * response header
  268. */
  269. morgan.token('res', function getResponseHeader (req, res, field) {
  270. if (!headersSent(res)) {
  271. return undefined
  272. }
  273. // get header
  274. var header = res.getHeader(field)
  275. return Array.isArray(header)
  276. ? header.join(', ')
  277. : header
  278. })
  279. /**
  280. * Format a Date in the common log format.
  281. *
  282. * @private
  283. * @param {Date} dateTime
  284. * @return {string}
  285. */
  286. function clfdate (dateTime) {
  287. var date = dateTime.getUTCDate()
  288. var hour = dateTime.getUTCHours()
  289. var mins = dateTime.getUTCMinutes()
  290. var secs = dateTime.getUTCSeconds()
  291. var year = dateTime.getUTCFullYear()
  292. var month = CLF_MONTH[dateTime.getUTCMonth()]
  293. return pad2(date) + '/' + month + '/' + year +
  294. ':' + pad2(hour) + ':' + pad2(mins) + ':' + pad2(secs) +
  295. ' +0000'
  296. }
  297. /**
  298. * Compile a format string into a function.
  299. *
  300. * @param {string} format
  301. * @return {function}
  302. * @public
  303. */
  304. function compile (format) {
  305. if (typeof format !== 'string') {
  306. throw new TypeError('argument format must be a string')
  307. }
  308. var fmt = String(JSON.stringify(format))
  309. var js = ' "use strict"\n return ' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function (_, name, arg) {
  310. var tokenArguments = 'req, res'
  311. var tokenFunction = 'tokens[' + String(JSON.stringify(name)) + ']'
  312. if (arg !== undefined) {
  313. tokenArguments += ', ' + String(JSON.stringify(arg))
  314. }
  315. return '" +\n (' + tokenFunction + '(' + tokenArguments + ') || "-") + "'
  316. })
  317. // eslint-disable-next-line no-new-func
  318. return new Function('tokens, req, res', js)
  319. }
  320. /**
  321. * Create a basic buffering stream.
  322. *
  323. * @param {object} stream
  324. * @param {number} interval
  325. * @public
  326. */
  327. function createBufferStream (stream, interval) {
  328. var buf = []
  329. var timer = null
  330. // flush function
  331. function flush () {
  332. timer = null
  333. stream.write(buf.join(''))
  334. buf.length = 0
  335. }
  336. // write function
  337. function write (str) {
  338. if (timer === null) {
  339. timer = setTimeout(flush, interval)
  340. }
  341. buf.push(str)
  342. }
  343. // return a minimal "stream"
  344. return { write: write }
  345. }
  346. /**
  347. * Define a format with the given name.
  348. *
  349. * @param {string} name
  350. * @param {string|function} fmt
  351. * @public
  352. */
  353. function format (name, fmt) {
  354. morgan[name] = fmt
  355. return this
  356. }
  357. /**
  358. * Lookup and compile a named format function.
  359. *
  360. * @param {string} name
  361. * @return {function}
  362. * @public
  363. */
  364. function getFormatFunction (name) {
  365. // lookup format
  366. var fmt = morgan[name] || name || morgan.default
  367. // return compiled format
  368. return typeof fmt !== 'function'
  369. ? compile(fmt)
  370. : fmt
  371. }
  372. /**
  373. * Get request IP address.
  374. *
  375. * @private
  376. * @param {IncomingMessage} req
  377. * @return {string}
  378. */
  379. function getip (req) {
  380. return req.ip ||
  381. req._remoteAddress ||
  382. (req.connection && req.connection.remoteAddress) ||
  383. undefined
  384. }
  385. /**
  386. * Determine if the response headers have been sent.
  387. *
  388. * @param {object} res
  389. * @returns {boolean}
  390. * @private
  391. */
  392. function headersSent (res) {
  393. // istanbul ignore next: node.js 0.8 support
  394. return typeof res.headersSent !== 'boolean'
  395. ? Boolean(res._header)
  396. : res.headersSent
  397. }
  398. /**
  399. * Pad number to two digits.
  400. *
  401. * @private
  402. * @param {number} num
  403. * @return {string}
  404. */
  405. function pad2 (num) {
  406. var str = String(num)
  407. // istanbul ignore next: num is current datetime
  408. return (str.length === 1 ? '0' : '') + str
  409. }
  410. /**
  411. * Record the start time.
  412. * @private
  413. */
  414. function recordStartTime () {
  415. this._startAt = process.hrtime()
  416. this._startTime = new Date()
  417. }
  418. /**
  419. * Define a token function with the given name,
  420. * and callback fn(req, res).
  421. *
  422. * @param {string} name
  423. * @param {function} fn
  424. * @public
  425. */
  426. function token (name, fn) {
  427. morgan[name] = fn
  428. return this
  429. }