visionmedia / page.js

Micro client-side router inspired by the Express router
http://visionmedia.github.com/page.js
7.67k stars 687 forks source link

How to exclude certain path in page.js? #566

Open kresnasatya opened 3 years ago

kresnasatya commented 3 years ago

Hi, is there any method to ignore certain path in page.js? Example, I have /api/* path that load list of API in my project and I want this path should not execute by page.js. I'm looking in documentation there's no mention about how to do that. Cc @matthewp.

axelpale commented 3 years ago

Hi satyakresna, I am looking for the same behaviour. In my case, I would like to serve uploaded files without page.js catching the attempts. In my app, users sometimes create links to point to certain file uploads, let say <a href="/uploads/1234/img.jpg">this image</a>. I would like to click on the link and let the browser exit the page and navigate to the url. However, if I click on the link, page.js catches the attempt, does not find a route for it and passes it to my default route page('*', handleError404).

One approach, yet unsufficient, is to require users to specify target="_blank" or rel="external" attributes. These attributes seem to prevent page.js routing. However, it feels unnecessary complicated to ask users to do that.

Instead, I would like to place a dedicated route for uploads. If users attempt to navigate to a path /uploads/... then the dedicated route would catch the attempt and let the browser to exit the page and load the upload image. The route code could look something like below:

page('/uploads/*', function () {
  // exit and go to /uploads/1234/img.jpg
})

page('/account', function () {
  render(accountView)
})

page('*', function () {
  render(error404View)
})

How to do this? What to write in the ´/uploads/*` handler function?

axelpale commented 3 years ago

After trying out different approaches, the only one that works was hinted in https://github.com/visionmedia/page.js/issues/317 and adapted to my case as below:

page('/uploads/*', function (ctx) {
  page.stop()
  ctx.handled = false
  window.location.href = ctx.canonicalPath
})

The problem seems to be that before the execution reaches the route handled, the page.js internals have already called pushState and set other stuff. Therefore the browser thinks we are already at /uploads/1234/img.jpg at the time the execution reaches the route handler furthermore complicating redirects done within the route handler.

To break the history chain, Page.js must somehow tell the browser that the next url will not be handled by page.js. I guess page.stop() and ctx.handled = false do their magic in this regard.