@@ -75,15 +75,47 @@ const asyncMiddleware = (fn) => (req, res, next) => {
7575 Promise . resolve ( fn ( req , res , next ) ) . catch ( next )
7676}
7777
78- // The IP address that Fastly regards as the true client making the request w/ fallback to req.ip
79- morgan . token ( 'client-ip' , ( req ) => req . headers [ 'fastly-client-ip' ] || req . ip )
80- const productionLogFormat = `:client-ip - ":method :url" :status - :response-time ms`
78+ // By default, `:remote-addr` is described as following in the morgon docs:
79+ //
80+ // The remote address of the request. This will use req.ip, otherwise
81+ // the standard req.connection.remoteAddress value (socket address).
82+ //
83+ // But in production, by default, `req.ip` is the IP of the Azure machine
84+ // which is something like "104.156.87.177:28244" which is *not* the
85+ // end user. BUT! Because we configure `app.set('trust proxy', true)`
86+ // *before* morgain is enabled, it will use the first entry from
87+ // the `x-forwarded-for` header which is looking like this:
88+ // "75.40.90.27, 157.52.111.52, 104.156.87.177:5786" which is
89+ // "{USER'S IP}, {FASTLY'S POP IP}, {AZURE'S IP}".
90+ // Incidentally, that first IP in the comma separated list is the
91+ // same as the value of `req.headers['fastly-client-ip']` but
92+ // Fastly will put that into the X-Forwarded-IP.
93+ // By leaning in to X-Forwarded-IP (*and* the use
94+ // `app.set('trust proxy', true)`) we can express ourselves here
95+ // without having to use vendor specific headers.
96+ const productionLogFormat = `:remote-addr - ":method :url" :status - :response-time ms`
8197
8298export default function ( app ) {
8399 // *** Request connection management ***
84100 if ( ! isTest ) app . use ( timeout )
85101 app . use ( abort )
86102
103+ // Don't use the proxy's IP, use the requester's for rate limiting or
104+ // logging.
105+ // See https://expressjs.com/en/guide/behind-proxies.html
106+ // Essentially, setting this means it believe that the IP is the
107+ // first of the `X-Forwarded-For` header values.
108+ // If it was 0 (or false), the value would be that
109+ // of `req.socket.remoteAddress`.
110+ // Now, the `req.ip` becomes the first entry from x-forwarded-for
111+ // and falls back on `req.socket.remoteAddress` in all other cases.
112+ // Their documentation says:
113+ //
114+ // If true, the client's IP address is understood as the
115+ // left-most entry in the X-Forwarded-For header.
116+ //
117+ app . set ( 'trust proxy' , true )
118+
87119 // *** Request logging ***
88120 // Enabled in development and azure deployed environments
89121 // Not enabled in Heroku because the Heroku router + papertrail already logs the request information
@@ -181,13 +213,6 @@ export default function (app) {
181213 }
182214
183215 // *** Early exits ***
184- // Don't use the proxy's IP, use the requester's for rate limiting
185- // See https://expressjs.com/en/guide/behind-proxies.html
186- // Essentially, setting this means it believe that the IP is the
187- // first of the `X-Forwarded-For` header values.
188- // If it was 0 (or false), the value would be that
189- // of `req.socket.remoteAddress`.
190- app . set ( 'trust proxy' , 1 )
191216 app . use ( rateLimit )
192217 app . use ( instrument ( handleInvalidPaths , './handle-invalid-paths' ) )
193218 app . use ( asyncMiddleware ( instrument ( handleNextDataPath , './handle-next-data-path' ) ) )
0 commit comments