Skip to content

How to rewrite URLs to local or remote destinations

Lloyd Brookes edited this page May 24, 2020 · 17 revisions

Note: For all example commands below, Windows users may need to use double instead of single quotes.

Local targets

The syntax is:

$ ws --rewrite '<source route> -> <destination route>'

For example, the client requested /css/style.css but you'd prefer to serve /css/new-theme.css instead.

$ ws --rewrite '/css/style.css -> /css/new-theme.css'

Re-route requests for stylesheets in the /css folder to the /build/css/ folder. Routes are specified using path-to-regexp v3 routing syntax. This syntax is virtually identical to Express v4 routing syntax except for the wildcard expressions, which should be written as (.*) instead of *.

$ ws --rewrite '/css/:stylesheet -> /build/css/:stylesheet'

Re-route the entire directory structure under /css/ to /build/css/ (this rewrites /css/a as /build/css/a, /css/a/b/c as /build/css/a/b/c etc.). In the replace expression, use $1, $2 etc to replace each matched group.

$ ws --rewrite '/css/(.*) -> /build/css/$1'

Remote targets

If the to URL contains a remote host, local-web-server will act as a proxy fetching and responding with the remote resource.

Mount the npm registry locally:

$ ws --rewrite '/npm/(.*) -> http://registry.npmjs.org/$1'

Map local requests for repo data to the Github API:

$ ws --rewrite '/:user/repos/:name -> https://api.github.com/repos/:user/:name'

Multiple rules

To specify multiple rules on the command line you can supply either a list of values:

$ ws --rewrite '.xhtml -> .html' '/posts/:id -> /data/:id.json'

Or set the --rewrite option multiple times. Both have the same effect.

$ ws --rewrite '.xhtml -> .html' --log.format stats --rewrite '/posts/:id -> /data/:id.json'

Usage in stored config

Rewrite rules should be stored in the config file as an array of { from: string, to: string } objects.

module.exports = {
  rewrite: [
    {
      from: '/css/(.*)', 
      to: '/build/styles/$1'
    },
    { 
      from: '/:user/repos/:name', 
      to: 'https://api.github.com/repos/:user/:name'
    }
  ]
}

You could vary which backend API service is queried based on an environment variable.

const server = process.env.ENV === 'STAGING'
  ? 'staging-api'
  : 'api'

module.exports = {
  rewrite: [
    {
      from: '/v1/(.*)', 
      to: `https://${server}.example.com/v1/$1`
    }
  ]
}

Verbose output

To filter the verbose output to show only rewrite activity, set --verbose.include middleware.rewrite.

$ ws --rewrite '/posts/:id -> /data/:id.json' --verbose.include middleware.rewrite
{
  'middleware.rewrite.config': { rewrite: [ { from: '/posts/:id', to: '/data/:id.json' } ] }
}

Now, when you make requests...

$ curl http://127.0.0.1:8000/posts/10

...you will see a JSON stream of debug output from the server.

{
  'middleware.rewrite.local': { from: '/posts/10', to: '/data/10.json' }
}

Debugging

The lws-rewrite package includes a trivial command-line tool for testing rewrite rules. Test an individual rule using this command structure:

$ npx lws-rewrite <from> <to> <url>

If the supplied <url> matches the <from> route then the command's output will be rewritten URL, else the original <url>.

Examples

Test a rule rewriting a local path (containing one named parameter) to a remote server.

$ npx lws-rewrite '/npm/:pkg' 'https://npmjs.org/package/:pkg' '/npm/renamer'
https://npmjs.org/package/renamer

Test a rule rewriting requests for files in the the /css/ folder to the /dist/css/ folder.

$ npx lws-rewrite '/css/(.*)' '/dist/css/$1' '/css/styles.css'
/dist/css/styles.css

If the supplied url does not match the rule it remains unmodified.

$ npx lws-rewrite '/css/(.*)' '/dist/css/$1' 'public/css/styles.css'
public/css/styles.css

Optional: add lws-rewrite to the dependency tree (if not already present) to speed up the above npx lws-rewrite commands.

$ npm install --save-dev lws-rewrite
Clone this wiki locally