question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`req.params` includes port number, regression `0.35.0`-`0.36.0`

See original GitHub issue

Describe the bug

When upgrading msw@0.35.0 to latest I noticed one of my utility method started to fail. I narrowed this issue to msw@0.36.0.

Some background. Not necessary for the bug but gives some insight.

I have a utility method which validates that all req.params values are encrypted. I have a specific pattern which can be utilized to identify such fields. For now lets call this pattern /somepattern/.

function validateQueryParametersAreEncrypted(request) {
    Object.entries(request.params).forEach(([name, value]) => {
        if (!/somepattern/.test(value)) {
            throw new Error(`URL parameter (${name}) was not encrypted: (${value})`);
        }
    });
}

This validation is applied to all my MSW handlers. It is now failing due to :3000 not matching /somepattern/.

Environment

  • msw: 0.36.3
  • nodejs: 16.13.1
  • npm: 8.3.0

Please also provide your browser version.

  • Google Chrome 96

To Reproduce

Steps to reproduce the behavior:

  1. Setup https://github.com/mswjs/examples/tree/master/examples/rest-react
  2. Add new handler:
rest.get("/example/:id", (req, res, ctx) => {
    console.log("req.params", req.params);
    return res(ctx.status(200));
})
  1. Add new request: fetch("/example/someid");.

Expected behavior

Below is logs from different MSW versions. Version 0.35.0 works as expected.

rest.get("/example/:id", (req, res, ctx) => {
    console.log("req.params", req.params);
    // ^^ msw@0.35.0 req.params {id: 'someid'}
    // ^^ msw@0.36.0 req.params {3000: ':3000', id: 'someid'}
    // ^^ msw@0.36.1 req.params {3000: ':3000', id: 'someid'}
    // ^^ msw@0.36.2 req.params {3000: ':3000', id: 'someid'}
    // ^^ msw@0.36.3 req.params {3000: ':3000', id: 'someid'}

    return res(ctx.status(200));
});

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
AriPerkkiocommented, Jan 11, 2022

I was comparing the bundled coercePath and the one from source, and was able to find the likely root cause. It seems main branch contains unreleased changes which might have fixed these, https://github.com/mswjs/msw/pull/1028 (👋 @tdeekens).

Below is comparison between 0.36.3 and main.

coercePath msw@0.36.3
function coercePath(path) {
  return (
    path
      /**
       * Replace wildcards ("*") with unnamed capturing groups
       * because "path-to-regexp" doesn't support wildcards.
       * Ignore path parameter' modifiers (i.e. ":name*").
       */
      .replace(
        /([:a-zA-Z_-]*)(\*{1,2})+/g,
        (_, parameterName, wildcard) => {
          const expression = '(.*)'

          if (!parameterName) {
            return expression
          }

          return parameterName.startsWith(':')
            ? `${parameterName}${wildcard}`
            : `${parameterName}${expression}`
        },
      )
      /**
       * Escape the protocol so that "path-to-regexp" could match
       * absolute URL.
       * @see https://github.com/pillarjs/path-to-regexp/issues/259
       */
      .replace(/^([^\/]+)(:)(?=\/\/)/g, '$1\\$2')
  )
}

> coercePath('http://localhost:3000/example/:id')
> 'http\\://localhost:3000/example/:id'
//                   ^^ Incorrect
coercePath msw@main, unreleased
function coercePath(path) {
  return (
    path
      /**
       * Replace wildcards ("*") with unnamed capturing groups
       * because "path-to-regexp" doesn't support wildcards.
       * Ignore path parameter' modifiers (i.e. ":name*").
       */
      .replace(
        /([:a-zA-Z_-]*)(\*{1,2})+/g,
        (_, parameterName, wildcard) => {
          const expression = '(.*)'

          if (!parameterName) {
            return expression
          }

          return parameterName.startsWith(':')
            ? `${parameterName}${wildcard}`
            : `${parameterName}${expression}`
        },
      )
      /**
       * Escape the port so that "path-to-regexp" can match
       * absolute URLs including port numbers.
       */
      .replace(/([^\/])(:)(?=\d+)/, '$1\\$2')
      /**
       * Escape the protocol so that "path-to-regexp" could match
       * absolute URL.
       * @see https://github.com/pillarjs/path-to-regexp/issues/259
       */
      .replace(/^([^\/]+)(:)(?=\/\/)/, '$1\\$2')
  )
}

> coercePath('http://localhost:3000/example/:id')
> 'http\\://localhost\\:3000/example/:id'
//                   ^^ Correct

So it seems coercePath will be buggy in releases 0.36.0 - 0.36.3 only. Once new version is released I can do the final verification.

1reaction
AriPerkkiocommented, Jan 11, 2022

Fix verified with version 0.36.4 - port number is no longer included in the req.params. Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Express.js req.params Property - GeeksforGeeks
The req. params property is an object containing properties mapped to the named route “parameters”. For example, if you have the route /student ......
Read more >
Why does req.params return an empty array? - Stack Overflow
req.params only contain the route params, not query string params (from GET) and not body params (from POST). The param() function however checks...
Read more >
What is req.params in Express.js? - Educative.io
req.params is an object of the req object that contains route parameters. If the params are specified when a URL is built, then...
Read more >
How To Retrieve URL and POST Parameters with Express
req.params can be used to retrieve values from routes. Consider the following URL: http://localhost:8080/api/1. This URL includes routes for ...
Read more >
Node and Express for Beginners - James Q Quick
We are defining the path for this route to include the id as a query parameter. Here's the code. app.get("/books/:id", (req, res) =>...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found