Skip to content

Commit

Permalink
fix(middleware): consider localhost variations (#31603)
Browse files Browse the repository at this point in the history
Since `localhost` is actually an alias for `127.0.0.1` that points to loopback, we should take that into consideration at `NextURL` when we handle local URLs.

The implementation is based on [is-localhost-url](https://github.com/Kikobeats/is-localhost-url); I added some tests over local URLs variations present at the library to ensure other variations are working fine.

Additionally, I refactor some things over the code to avoid doing the same twice and added some legibility that is always welcome when you are working with URLs stuff.

 closes #31533
  • Loading branch information
Kikobeats authored Nov 19, 2021
1 parent 9652bdd commit f52211b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
21 changes: 15 additions & 6 deletions packages/next/server/web/next-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ interface Options {
trailingSlash?: boolean
}

const REGEX_LOCALHOST_HOSTNAME =
/(?!^https?:\/\/)(127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}|::1)/

export class NextURL extends URL {
private _basePath: string
private _locale?: {
Expand All @@ -33,11 +36,12 @@ export class NextURL extends URL {
private _options: Options
private _url: URL

constructor(url: string, options: Options = {}) {
super(formatRelative(url))
constructor(input: string, options: Options = {}) {
const url = createWHATWGURL(input)
super(url)
this._options = options
this._basePath = ''
this._url = formatRelative(url)
this._url = url
this.analyzeUrl()
}

Expand Down Expand Up @@ -163,7 +167,7 @@ export class NextURL extends URL {
}

set href(url: string) {
this._url = formatRelative(url)
this._url = createWHATWGURL(url)
this.analyzeUrl()
}

Expand Down Expand Up @@ -228,8 +232,13 @@ export class NextURL extends URL {
}
}

function formatRelative(url: string) {
return url.startsWith('/')
function createWHATWGURL(url: string) {
url = url.replace(REGEX_LOCALHOST_HOSTNAME, 'localhost')
return isRelativeURL(url)
? new URL(url.replace(/^\/+/, '/'), new URL('https://localhost'))
: new URL(url)
}

function isRelativeURL(url: string) {
return url.startsWith('/')
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,15 @@ it('parses and formats the default locale', () => {
expect(url.locale).toEqual('fr')
expect(url.toString()).toEqual('/root/fr/bar')
})

it('consider 127.0.0.1 and variations as localhost', () => {
const httpUrl = new NextURL('http://localhost:3000/hello')
expect(new NextURL('http://127.0.0.1:3000/hello')).toStrictEqual(httpUrl)
expect(new NextURL('http://127.0.1.0:3000/hello')).toStrictEqual(httpUrl)
expect(new NextURL('http://::1:3000/hello')).toStrictEqual(httpUrl)

const httpsUrl = new NextURL('https://localhost:3000/hello')
expect(new NextURL('https://127.0.0.1:3000/hello')).toStrictEqual(httpsUrl)
expect(new NextURL('https://127.0.1.0:3000/hello')).toStrictEqual(httpsUrl)
expect(new NextURL('https://::1:3000/hello')).toStrictEqual(httpsUrl)
})

1 comment on commit f52211b

@ijjk
Copy link
Member

@ijjk ijjk commented on f52211b Nov 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stats from current release

Default Build (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
buildDuration 17.9s 18.4s ⚠️ +474ms
buildDurationCached 3.6s 3.6s ⚠️ +9ms
nodeModulesSize 339 MB 339 MB ⚠️ +17.6 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
/ failed reqs 0 0
/ total time (seconds) 2.91 2.962 ⚠️ +0.05
/ avg req/sec 859.14 844.09 ⚠️ -15.05
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.34 1.396 ⚠️ +0.06
/error-in-render avg req/sec 1866.16 1790.83 ⚠️ -75.33
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
450.HASH.js gzip 179 B 179 B
framework-HASH.js gzip 42.2 kB 42.2 kB
main-HASH.js gzip 28.3 kB 28.3 kB ⚠️ +15 B
webpack-HASH.js gzip 1.45 kB 1.45 kB
Overall change 72.2 kB 72.2 kB ⚠️ +15 B
Legacy Client Bundles (polyfills)
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
_app-HASH.js gzip 1.37 kB 1.37 kB
_error-HASH.js gzip 194 B 194 B
amp-HASH.js gzip 312 B 312 B
css-HASH.js gzip 327 B 327 B
dynamic-HASH.js gzip 2.38 kB 2.38 kB
head-HASH.js gzip 350 B 350 B
hooks-HASH.js gzip 635 B 635 B
image-HASH.js gzip 4.44 kB 4.45 kB ⚠️ +1 B
index-HASH.js gzip 263 B 263 B
link-HASH.js gzip 1.87 kB 1.87 kB
routerDirect..HASH.js gzip 321 B 321 B
script-HASH.js gzip 383 B 383 B
withRouter-HASH.js gzip 318 B 318 B
85e02e95b279..7e3.css gzip 107 B 107 B
Overall change 13.3 kB 13.3 kB ⚠️ +1 B
Client Build Manifests
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
_buildManifest.js gzip 460 B 460 B
Overall change 460 B 460 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
index.html gzip 523 B 532 B ⚠️ +9 B
link.html gzip 536 B 545 B ⚠️ +9 B
withRouter.html gzip 517 B 527 B ⚠️ +10 B
Overall change 1.58 kB 1.6 kB ⚠️ +28 B

Diffs

Diff for _buildManifest.js
@@ -12,8 +12,8 @@ self.__BUILD_MANIFEST = {
   ],
   "/head": ["static\u002Fchunks\u002Fpages\u002Fhead-7100d3b2a548f0e4.js"],
   "/hooks": ["static\u002Fchunks\u002Fpages\u002Fhooks-ff60bc61acd2698b.js"],
-  "/image": ["static\u002Fchunks\u002Fpages\u002Fimage-2a8b03d7b35abada.js"],
-  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-fa969765a079642e.js"],
+  "/image": ["static\u002Fchunks\u002Fpages\u002Fimage-91f7c5ff8695376c.js"],
+  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-678af336607f5345.js"],
   "/routerDirect": [
     "static\u002Fchunks\u002Fpages\u002FrouterDirect-76232dd6bc335a24.js"
   ],
Diff for image-HASH.js
@@ -9,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/image",
         function() {
-          return __webpack_require__(3155);
+          return __webpack_require__(5924);
         }
       ]);
       if (false) {
@@ -969,7 +969,7 @@
       /***/
     },
 
-    /***/ 3155: /***/ function(
+    /***/ 5924: /***/ function(
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
Diff for link-HASH.js
@@ -184,7 +184,6 @@
           shallow = props.shallow,
           scroll = props.scroll,
           locale = props.locale;
-        // Deprecated. Warning shown by propType check. If the children provided is a string (<Link>example</Link>) we wrap it in an <a> tag
         if (typeof children === "string") {
           children = /*#__PURE__*/ _react.default.createElement(
             "a",
Diff for main-HASH.js
@@ -590,7 +590,7 @@
         document.getElementById("__NEXT_DATA__").textContent
       );
       window.__NEXT_DATA__ = data;
-      var version = "12.0.4";
+      var version = "12.0.5-canary.5";
       exports.version = version;
       var looseToArray = function(input) {
         return [].slice.call(input);
@@ -2272,31 +2272,31 @@
             var _this = this;
             return withFuture(route, routes, function() {
               var _this1 = _this;
-              var routeFilesPromise = getFilesForRoute(assetPrefix, route)
-                .then(function(param) {
-                  var scripts = param.scripts,
-                    css = param.css;
-                  return Promise.all([
-                    entrypoints.has(route)
-                      ? []
-                      : Promise.all(scripts.map(maybeExecuteScript)),
-                    Promise.all(css.map(fetchStyleSheet))
-                  ]);
-                })
-                .then(function(res) {
-                  return _this1
-                    .whenEntrypoint(route)
-                    .then(function(entrypoint) {
-                      return {
-                        entrypoint: entrypoint,
-                        styles: res[1]
-                      };
-                    });
-                });
+              var devBuildPromiseResolve;
               if (false) {
               }
               return resolvePromiseWithTimeout(
-                routeFilesPromise,
+                getFilesForRoute(assetPrefix, route)
+                  .then(function(param) {
+                    var scripts = param.scripts,
+                      css = param.css;
+                    return Promise.all([
+                      entrypoints.has(route)
+                        ? []
+                        : Promise.all(scripts.map(maybeExecuteScript)),
+                      Promise.all(css.map(fetchStyleSheet))
+                    ]);
+                  })
+                  .then(function(res) {
+                    return _this1
+                      .whenEntrypoint(route)
+                      .then(function(entrypoint) {
+                        return {
+                          entrypoint: entrypoint,
+                          styles: res[1]
+                        };
+                      });
+                  }),
                 MS_MAX_IDLE_DELAY,
                 markAssetError(
                   new Error("Route did not complete loading: ".concat(route))
@@ -2321,6 +2321,12 @@
                   return {
                     error: err
                   };
+                })
+                .finally(function() {
+                  return devBuildPromiseResolve === null ||
+                    devBuildPromiseResolve === void 0
+                    ? void 0
+                    : devBuildPromiseResolve();
                 });
             });
           },
Diff for index.html
@@ -19,7 +19,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/main-11921b61f92a7ca9.js"
+      src="/_next/static/chunks/main-4886342f1acf4585.js"
       defer=""
     ></script>
     <script
@@ -38,7 +38,7 @@
     ></script>
   </head>
   <body>
-    <div id="__next">Hello world 👋</div>
+    <div id="__next" data-reactroot="">Hello world 👋</div>
     <script id="__NEXT_DATA__" type="application/json">
       {
         "props": { "pageProps": {}, "__N_SSP": true },
Diff for link.html
@@ -19,7 +19,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/main-11921b61f92a7ca9.js"
+      src="/_next/static/chunks/main-4886342f1acf4585.js"
       defer=""
     ></script>
     <script
@@ -27,7 +27,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/link-fa969765a079642e.js"
+      src="/_next/static/chunks/pages/link-678af336607f5345.js"
       defer=""
     ></script>
     <script src="/_next/static/BUILD_ID/_buildManifest.js" defer=""></script>
@@ -38,7 +38,7 @@
     ></script>
   </head>
   <body>
-    <div id="__next">
+    <div id="__next" data-reactroot="">
       <div>
         <h3>A Link page!</h3>
         <a href="/">Go to /</a>
Diff for withRouter.html
@@ -19,7 +19,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/main-11921b61f92a7ca9.js"
+      src="/_next/static/chunks/main-4886342f1acf4585.js"
       defer=""
     ></script>
     <script
@@ -38,7 +38,7 @@
     ></script>
   </head>
   <body>
-    <div id="__next"><div>I use withRouter</div></div>
+    <div id="__next" data-reactroot=""><div>I use withRouter</div></div>
     <script id="__NEXT_DATA__" type="application/json">
       {
         "props": { "pageProps": {}, "__N_SSP": true },

Default Build with SWC (Increase detected ⚠️)
General Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
buildDuration 19.7s 19.6s -50ms
buildDurationCached 3.5s 3.7s ⚠️ +119ms
nodeModulesSize 339 MB 339 MB ⚠️ +17.6 kB
Page Load Tests Overall decrease ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
/ failed reqs 0 0
/ total time (seconds) 2.911 2.966 ⚠️ +0.06
/ avg req/sec 858.71 842.9 ⚠️ -15.81
/error-in-render failed reqs 0 0
/error-in-render total time (seconds) 1.392 1.418 ⚠️ +0.03
/error-in-render avg req/sec 1795.69 1762.56 ⚠️ -33.13
Client Bundles (main, webpack, commons) Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
450.HASH.js gzip 179 B 179 B
framework-HASH.js gzip 42.3 kB 42.3 kB
main-HASH.js gzip 28.5 kB 28.6 kB ⚠️ +20 B
webpack-HASH.js gzip 1.44 kB 1.44 kB
Overall change 72.5 kB 72.5 kB ⚠️ +20 B
Legacy Client Bundles (polyfills)
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
polyfills-HASH.js gzip 31 kB 31 kB
Overall change 31 kB 31 kB
Client Pages Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
_app-HASH.js gzip 1.35 kB 1.35 kB
_error-HASH.js gzip 180 B 180 B
amp-HASH.js gzip 305 B 305 B
css-HASH.js gzip 321 B 321 B
dynamic-HASH.js gzip 2.38 kB 2.38 kB
head-HASH.js gzip 342 B 342 B
hooks-HASH.js gzip 622 B 622 B
image-HASH.js gzip 4.46 kB 4.47 kB ⚠️ +1 B
index-HASH.js gzip 256 B 256 B
link-HASH.js gzip 1.91 kB 1.91 kB
routerDirect..HASH.js gzip 314 B 314 B
script-HASH.js gzip 375 B 375 B
withRouter-HASH.js gzip 309 B 309 B
85e02e95b279..7e3.css gzip 107 B 107 B
Overall change 13.2 kB 13.2 kB ⚠️ +1 B
Client Build Manifests Overall decrease ✓
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
_buildManifest.js gzip 460 B 459 B -1 B
Overall change 460 B 459 B -1 B
Rendered Page Sizes Overall increase ⚠️
vercel/next.js canary v12.0.4 vercel/next.js refs/heads/canary Change
index.html gzip 524 B 532 B ⚠️ +8 B
link.html gzip 535 B 545 B ⚠️ +10 B
withRouter.html gzip 517 B 526 B ⚠️ +9 B
Overall change 1.58 kB 1.6 kB ⚠️ +27 B

Diffs

Diff for _buildManifest.js
@@ -12,8 +12,8 @@ self.__BUILD_MANIFEST = {
   ],
   "/head": ["static\u002Fchunks\u002Fpages\u002Fhead-7100d3b2a548f0e4.js"],
   "/hooks": ["static\u002Fchunks\u002Fpages\u002Fhooks-ff60bc61acd2698b.js"],
-  "/image": ["static\u002Fchunks\u002Fpages\u002Fimage-2a8b03d7b35abada.js"],
-  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-fa969765a079642e.js"],
+  "/image": ["static\u002Fchunks\u002Fpages\u002Fimage-91f7c5ff8695376c.js"],
+  "/link": ["static\u002Fchunks\u002Fpages\u002Flink-678af336607f5345.js"],
   "/routerDirect": [
     "static\u002Fchunks\u002Fpages\u002FrouterDirect-76232dd6bc335a24.js"
   ],
Diff for image-HASH.js
@@ -9,7 +9,7 @@
       (window.__NEXT_P = window.__NEXT_P || []).push([
         "/image",
         function() {
-          return __webpack_require__(3155);
+          return __webpack_require__(5924);
         }
       ]);
       if (false) {
@@ -969,7 +969,7 @@
       /***/
     },
 
-    /***/ 3155: /***/ function(
+    /***/ 5924: /***/ function(
       __unused_webpack_module,
       __webpack_exports__,
       __webpack_require__
Diff for link-HASH.js
@@ -184,7 +184,6 @@
           shallow = props.shallow,
           scroll = props.scroll,
           locale = props.locale;
-        // Deprecated. Warning shown by propType check. If the children provided is a string (<Link>example</Link>) we wrap it in an <a> tag
         if (typeof children === "string") {
           children = /*#__PURE__*/ _react.default.createElement(
             "a",
Diff for main-HASH.js
@@ -590,7 +590,7 @@
         document.getElementById("__NEXT_DATA__").textContent
       );
       window.__NEXT_DATA__ = data;
-      var version = "12.0.4";
+      var version = "12.0.5-canary.5";
       exports.version = version;
       var looseToArray = function(input) {
         return [].slice.call(input);
@@ -2272,31 +2272,31 @@
             var _this = this;
             return withFuture(route, routes, function() {
               var _this1 = _this;
-              var routeFilesPromise = getFilesForRoute(assetPrefix, route)
-                .then(function(param) {
-                  var scripts = param.scripts,
-                    css = param.css;
-                  return Promise.all([
-                    entrypoints.has(route)
-                      ? []
-                      : Promise.all(scripts.map(maybeExecuteScript)),
-                    Promise.all(css.map(fetchStyleSheet))
-                  ]);
-                })
-                .then(function(res) {
-                  return _this1
-                    .whenEntrypoint(route)
-                    .then(function(entrypoint) {
-                      return {
-                        entrypoint: entrypoint,
-                        styles: res[1]
-                      };
-                    });
-                });
+              var devBuildPromiseResolve;
               if (false) {
               }
               return resolvePromiseWithTimeout(
-                routeFilesPromise,
+                getFilesForRoute(assetPrefix, route)
+                  .then(function(param) {
+                    var scripts = param.scripts,
+                      css = param.css;
+                    return Promise.all([
+                      entrypoints.has(route)
+                        ? []
+                        : Promise.all(scripts.map(maybeExecuteScript)),
+                      Promise.all(css.map(fetchStyleSheet))
+                    ]);
+                  })
+                  .then(function(res) {
+                    return _this1
+                      .whenEntrypoint(route)
+                      .then(function(entrypoint) {
+                        return {
+                          entrypoint: entrypoint,
+                          styles: res[1]
+                        };
+                      });
+                  }),
                 MS_MAX_IDLE_DELAY,
                 markAssetError(
                   new Error("Route did not complete loading: ".concat(route))
@@ -2321,6 +2321,12 @@
                   return {
                     error: err
                   };
+                })
+                .finally(function() {
+                  return devBuildPromiseResolve === null ||
+                    devBuildPromiseResolve === void 0
+                    ? void 0
+                    : devBuildPromiseResolve();
                 });
             });
           },
Diff for index.html
@@ -19,7 +19,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/main-11921b61f92a7ca9.js"
+      src="/_next/static/chunks/main-4886342f1acf4585.js"
       defer=""
     ></script>
     <script
@@ -38,7 +38,7 @@
     ></script>
   </head>
   <body>
-    <div id="__next">Hello world 👋</div>
+    <div id="__next" data-reactroot="">Hello world 👋</div>
     <script id="__NEXT_DATA__" type="application/json">
       {
         "props": { "pageProps": {}, "__N_SSP": true },
Diff for link.html
@@ -19,7 +19,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/main-11921b61f92a7ca9.js"
+      src="/_next/static/chunks/main-4886342f1acf4585.js"
       defer=""
     ></script>
     <script
@@ -27,7 +27,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/pages/link-fa969765a079642e.js"
+      src="/_next/static/chunks/pages/link-678af336607f5345.js"
       defer=""
     ></script>
     <script src="/_next/static/BUILD_ID/_buildManifest.js" defer=""></script>
@@ -38,7 +38,7 @@
     ></script>
   </head>
   <body>
-    <div id="__next">
+    <div id="__next" data-reactroot="">
       <div>
         <h3>A Link page!</h3>
         <a href="/">Go to /</a>
Diff for withRouter.html
@@ -19,7 +19,7 @@
       defer=""
     ></script>
     <script
-      src="/_next/static/chunks/main-11921b61f92a7ca9.js"
+      src="/_next/static/chunks/main-4886342f1acf4585.js"
       defer=""
     ></script>
     <script
@@ -38,7 +38,7 @@
     ></script>
   </head>
   <body>
-    <div id="__next"><div>I use withRouter</div></div>
+    <div id="__next" data-reactroot=""><div>I use withRouter</div></div>
     <script id="__NEXT_DATA__" type="application/json">
       {
         "props": { "pageProps": {}, "__N_SSP": true },

Please sign in to comment.