فهرست منبع

Merge pull request #5750 from overleaf/jpa-cache-req-ip

[web] cache req.ip and bail out in case none is available

GitOrigin-RevId: 07084114676ffd13530c9ad4e0ff386fc2c5fa17
Brian Gough 4 سال پیش
والد
کامیت
e9c7b0d17c
1فایلهای تغییر یافته به همراه33 افزوده شده و 0 حذف شده
  1. 33 0
      services/web/app/src/infrastructure/Server.js

+ 33 - 0
services/web/app/src/infrastructure/Server.js

@@ -76,6 +76,39 @@ if (Settings.behindProxy) {
     next()
   })
 }
+
+// `req.ip` is a getter on the underlying socket.
+// The socket details are freed as the connection is dropped -- aka aborted.
+// Hence `req.ip` may read `undefined` upon connection drop.
+// A couple of places require a valid IP at all times. Cache it!
+const ORIGINAL_REQ_IP = Object.getOwnPropertyDescriptor(
+  Object.getPrototypeOf(app.request),
+  'ip'
+).get
+Object.defineProperty(app.request, 'ip', {
+  configurable: true,
+  enumerable: true,
+  get: function ipWithCache() {
+    const ip = ORIGINAL_REQ_IP.call(this)
+    // Shadow the prototype level getter with a property on the instance.
+    // Any future access on `req.ip` will get served by the instance property.
+    Object.defineProperty(this, 'ip', { value: ip })
+    return ip
+  },
+})
+app.use(function (req, res, next) {
+  if (req.aborted) {
+    // Request has been aborted already.
+    return
+  }
+  // Implicitly cache the ip, see above.
+  if (!req.ip) {
+    // Critical connection details are missing.
+    return
+  }
+  next()
+})
+
 if (Settings.exposeHostname) {
   const HOSTNAME = require('os').hostname()
   app.use((req, res, next) => {