1

I want to render a new HTML page on user request, which is only accessible if the authorization header is set correctly. I initially thought that the browser would redirect to the page, but found out that this is not the case. I have found some ways to handle this, for example replacing the DOM, but I don't think that is a good solution.

Here is the fetch call from UI, which returns the HTML, but does not render it currently:

fetch('/protected_route', {
  headers: {
    'authorization': 'Bearer ' + sessionStorage.getItem('token')
  }
}).then(response => {
  // What to do with the response
});

Here is the server code, if that helps:

app.get('/protected_route', (req, res) => {
  const bearer = req.headers['authorization'];

  if(typeof bearer === 'undefined') {
    res.json({message: 'Not logged in'});
  }
  else {
    const token = bearer.split(' ')[1];

    jwt.verify(token, config.secret, (error, data) => {
      if(error) {
        res.json({message: 'Error verifying token'});
      }
      else {
        res.render('protected_route');
      }
    });
  }
});
VLAZ
  • 26,331
  • 9
  • 49
  • 67
leonphil
  • 15
  • 1
  • 4
  • 3
    `fetch` runs an HTTP request but it's meant to communicate with the server *without* leaving the current page. Since you're handling the authorization manually anyway, why not use a cookie instead? That way you can check the cookie in your `/protected_route` handler, then simply use an `` to let the user move to the page. –  Nov 19 '18 at 20:47
  • @ChrisG Thanks for the answer! I actually did not consider that option. I just redirected the user with `window.location.href=path` and it works now. – leonphil Nov 19 '18 at 21:01

2 Answers2

3

The problem you are facing is when you tried to open a new HTML page and send back an html file via res.render(), this will send HTML content back to request. When using API call via AJAX or fetch or request or any other API client they are developed for single page application and these calls prohibits browser from rendering to new html page. API calls from such sources process over data and browser have no control over response received.

If you need to render another HTML page than use form-submit to call API, as this is the only way that let browser act upon response, and display response in new page. Since res.render() returned HTML file content, thus a new page act like a file is opened.

If you want to use single page application then you had to process over HTML received in response and then replace whole loaded HTML with new one, you had to make changes in DOM if need to use some API call module.

You can check this github project explaining all basic front-end and backend links for starters.

NAVIN
  • 3,193
  • 4
  • 19
  • 32
  • 1
    `These response function can only send back data and not html file` to be clear: the server can absolutely send back an HTML file here, and it won't even be able to tell the difference between an AJAX request and the regular way. All it does is provide endpoints for requests. It is perfectly possible to (nonsensically) have the browser navigate to a JSON file, or to request and process an HTML file via AJAX. –  Nov 19 '18 at 21:54
  • 1
    What `res.render()` does is call the view engine, supplying a view file and optional parameters, then send back the resulting file, usually HTML. Again, replying with `res.render()` to an AJAX request is perfectly possible and can in fact be a useful implementation. The important thing any answer to the above question must include is that `fetch` is unsuitable when it comes to navigating programmatically using JS. –  Nov 19 '18 at 21:57
  • 1
    `If you need to render another html page than use form-submit to call API as this is the only way that let server render to other page` No, one can use `location.href = url;` to navigate elsewhere. Plus, again, the server only provides the reply. Whether the browser renders it or not depends on how the request was made, not on the commands the server-side code used. –  Nov 19 '18 at 22:02
  • 2
    That's what i been trying to say that these functions doesn't allow browser to display response provided by server and act as a middle ware to manipulate the data. And we had to make changes in DOM to reflect changes on HTML and we can append, replace old HTML with HTML provided in response. – NAVIN Nov 20 '18 at 06:52
  • Sorry, but your answer contains several statements that are plain wrong, and is very misleading. In my book it shows you know how to use the commands you reference, but you don't truly understand the processes involved. OP marked it as accepted, probably without really reading it, but it should be edited or removed imo. –  Nov 20 '18 at 09:53
  • Thank you, have updated my answer and yes I'm still learning. – NAVIN Nov 20 '18 at 11:28
  • @ChrisG Re:"fetch is unsuitable when it comes to navigating programmatically using JS.". What would you suggest then? What is your solution to navigate programatically and while using res.render() and passing dynamic data? and preferably avoiding cookies as well. – ttfreeman May 08 '19 at 18:37
  • @ttfreeman Regardless of the server implementation, navigating programmatically works by setting `location` to a new URL. For GET parameters you can simply append them: `location = "/user?id=123";`, a POST request is not as easy. The only method I know of is to append a hidden `
    ` to the document, add ``s containing the data, then submit it. Writing an appropriate helper function is relatively straightforward.
    –  May 08 '19 at 20:12
-3

The only way to solve it I've found is using document.write(data). This statement result in rendering the received page but inside the same document, not changing the browser window to the new page and not including a new enter in the history of the browser