Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

index.js 5.9 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
  1. const express = require('express')
  2. const instrument = require('../lib/instrument-middleware')
  3. const haltOnDroppedConnection = require('./halt-on-dropped-connection')
  4. const { NODE_ENV } = process.env
  5. const isDevelopment = NODE_ENV === 'development'
  6. const isTest = NODE_ENV === 'test' || process.env.GITHUB_ACTIONS === 'true'
  7. // Catch unhandled promise rejections and passing them to Express's error handler
  8. // https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016
  9. const asyncMiddleware = fn =>
  10. (req, res, next) => {
  11. Promise.resolve(fn(req, res, next)).catch(next)
  12. }
  13. module.exports = function (app) {
  14. // *** Request connection management ***
  15. if (!isTest) app.use(require('./timeout'))
  16. app.use(require('./abort'))
  17. // *** Development tools ***
  18. app.use(require('morgan')('dev', { skip: (req, res) => !isDevelopment }))
  19. if (isDevelopment) app.use(require('./webpack'))
  20. // *** Observability ***
  21. if (process.env.DD_API_KEY) {
  22. app.use(require('./connect-datadog'))
  23. }
  24. // *** Early exits ***
  25. // Don't use the proxy's IP, use the requester's for rate limiting
  26. // See https://expressjs.com/en/guide/behind-proxies.html
  27. app.set('trust proxy', 1)
  28. app.use(require('./rate-limit'))
  29. app.use(instrument('./handle-invalid-paths'))
  30. // *** Security ***
  31. app.use(require('./cors'))
  32. app.use(require('helmet')({
  33. // Override referrerPolicy to match the browser's default: "strict-origin-when-cross-origin".
  34. // Helmet now defaults to "no-referrer", which is a problem for our archived assets proxying.
  35. referrerPolicy: {
  36. policy: 'strict-origin-when-cross-origin'
  37. }
  38. }))
  39. app.use(require('./csp')) // Must come after helmet
  40. app.use(require('./cookie-parser')) // Must come before csrf
  41. app.use(express.json()) // Must come before csrf
  42. app.use(require('./csrf'))
  43. app.use(require('./handle-csrf-errors')) // Must come before regular handle-errors
  44. // *** Headers ***
  45. app.set('etag', false) // We will manage our own ETags if desired
  46. app.use(require('compression')())
  47. app.use(require('./disable-caching-on-safari'))
  48. app.use(require('./set-fastly-surrogate-key'))
  49. // *** Config and context for redirects ***
  50. app.use(require('./req-utils')) // Must come before record-redirect and events
  51. app.use(require('./record-redirect'))
  52. app.use(instrument('./detect-language')) // Must come before context, breadcrumbs, find-page, handle-errors, homepages
  53. app.use(asyncMiddleware(instrument('./context'))) // Must come before early-access-*, handle-redirects
  54. // *** Redirects, 3xx responses ***
  55. // I ordered these by use frequency
  56. app.use(require('connect-slashes')(false))
  57. app.use(instrument('./redirects/external'))
  58. app.use(instrument('./redirects/help-to-docs'))
  59. app.use(instrument('./redirects/language-code-redirects')) // Must come before contextualizers
  60. app.use(instrument('./redirects/handle-redirects')) // Must come before contextualizers
  61. // *** Config and context for rendering ***
  62. app.use(asyncMiddleware(instrument('./find-page'))) // Must come before archived-enterprise-versions, breadcrumbs, featured-links, products, render-page
  63. app.use(instrument('./block-robots'))
  64. // Check for a dropped connection before proceeding
  65. app.use(haltOnDroppedConnection)
  66. // *** Rendering, 2xx responses ***
  67. // I largely ordered these by use frequency
  68. app.use(asyncMiddleware(instrument('./archived-enterprise-versions-assets'))) // Must come before static/assets
  69. app.use('/dist', express.static('dist', {
  70. index: false,
  71. etag: false,
  72. immutable: true,
  73. lastModified: false,
  74. maxAge: '28 days' // Could be infinite given our fingerprinting
  75. }))
  76. app.use('/assets', express.static('assets', {
  77. index: false,
  78. etag: false,
  79. lastModified: false,
  80. maxAge: '1 day' // Relatively short in case we update images
  81. }))
  82. app.use('/public', express.static('data/graphql', {
  83. index: false,
  84. etag: false,
  85. lastModified: false,
  86. maxAge: '7 days' // A bit longer since releases are more sparse
  87. }))
  88. app.use('/events', asyncMiddleware(instrument('./events')))
  89. app.use('/search', asyncMiddleware(instrument('./search')))
  90. app.use(asyncMiddleware(instrument('./archived-enterprise-versions')))
  91. app.use(instrument('./robots'))
  92. app.use(/(\/.*)?\/early-access$/, instrument('./contextualizers/early-access-links'))
  93. app.use('/categories.json', asyncMiddleware(instrument('./categories-for-support')))
  94. app.use(instrument('./loaderio-verification'))
  95. app.get('/_500', asyncMiddleware(instrument('./trigger-error')))
  96. // Check for a dropped connection before proceeding (again)
  97. app.use(haltOnDroppedConnection)
  98. // *** Preparation for render-page: contextualizers ***
  99. app.use(asyncMiddleware(instrument('./contextualizers/release-notes')))
  100. app.use(instrument('./contextualizers/graphql'))
  101. app.use(instrument('./contextualizers/rest'))
  102. app.use(instrument('./contextualizers/webhooks'))
  103. app.use(asyncMiddleware(instrument('./contextualizers/whats-new-changelog')))
  104. app.use(instrument('./contextualizers/layout'))
  105. app.use(instrument('./contextualizers/current-product-tree'))
  106. app.use(asyncMiddleware(instrument('./contextualizers/generic-toc')))
  107. app.use(asyncMiddleware(instrument('./contextualizers/breadcrumbs')))
  108. app.use(asyncMiddleware(instrument('./contextualizers/early-access-breadcrumbs')))
  109. app.use(asyncMiddleware(instrument('./dev-toc')))
  110. app.use(asyncMiddleware(instrument('./featured-links')))
  111. app.use(asyncMiddleware(instrument('./learning-track')))
  112. // *** Headers for pages only ***
  113. app.use(require('./set-fastly-cache-headers'))
  114. // handle serving NextJS bundled code (/_next/*)
  115. if (process.env.FEATURE_NEXTJS) {
  116. app.use(instrument('./next'))
  117. }
  118. // Check for a dropped connection before proceeding (again)
  119. app.use(haltOnDroppedConnection)
  120. // *** Rendering, must go almost last ***
  121. app.get('/*', asyncMiddleware(instrument('./render-page')))
  122. // *** Error handling, must go last ***
  123. app.use(require('./handle-errors'))
  124. }
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...