0

I am trying to implement a Post-Redirect-Get design pattern into my code, which uses Express. What I have is:

var sessionVariable;

app.post('/user', function(req, res) {
    sessionVariable = req.session;

    // Sets a session variable to a token
    sessionVariable.token = req.body.token;

    // Redirect to /user
    return res.redirect('/user')
});
app.get('/user', function(req, res) {
    sessionVariable = req.session;

     if(sessionVariable.token){
        res.send('Logged in');
     } else {
        res.send('Not logged in');
     }
});

What I expect to happen is when the user submits a POST request to /user, it will define sessionVarlable.token, then redirect to /user again where it checks if a token exists.

What ends up happening is I will submit the POST request, and through console loggging I can see that app.post fires, but it does not re-direct. Instead, it seems to get stuck on the page where the POST request was omitted.

What is the reason for this?

Edit: Any res will not fire under app.post, e.g. res.send('test') doesn't work.

ethanc
  • 137
  • 2
  • 12
  • I don't think a redirect changes the HTTP method from `POST` to `GET`. Also, using globals like this is a really bad and unsafe practice. Imagine that two users attempt to log in at the same time, you create a race condition. – Patrick Roberts Jun 17 '18 at 23:01
  • @PatrickRoberts FWIW assuming this is `express-session` then this wouldn't be a global, session objects are user-scoped. OP - Is your POST call being made via AJAX by any chance? – James Jun 17 '18 at 23:15
  • @James `req.session` is user-scoped, `sessionVariable` is _not_. – Patrick Roberts Jun 17 '18 at 23:16
  • @James my POST request is run via the `request` node module. It looks like request.post('/user', { json: { token: json.access_token } }); – ethanc Jun 17 '18 at 23:18
  • @PatrickRoberts they're the same variable :/ not sure I'm seeing the same problem you are here - what's global about it? – James Jun 17 '18 at 23:21
  • @PatrickRoberts ok see the OP isn't declaring the var in the local scope, however, it's not an issue as it's always refetched from `req.session` – James Jun 17 '18 at 23:23
  • @James ahah, yeah I didn't notice the assignment happening in the `get` request. Still, it's bad to do that, just reference `req.session`. – Patrick Roberts Jun 17 '18 at 23:25
  • @PatrickRoberts yes, probably an oversight from the OP to be leaking a global but safe in this case. Ethan, that will be the problem, you can't redirect from an AJAX request....well you can, but unless you handle the response client side you won't get the desired behaviour. From the client you would need to perform a *page* POST e.g. `
    ...
    `
    – James Jun 17 '18 at 23:30
  • @James is there a way to POST via server-side? What I am doing is trying to is take `req.query.token` and pass that to app.get. The issue is that when redirecting using `res.redirect('user?token=123456789)` , it shows the token in the search bar and I don't want the query string to show. – ethanc Jun 17 '18 at 23:32
  • @ethanc as already explained, you won't be able to achieve the desired outcome without handling this at the client. Why aren't you just returning `token` in the POST response and then have the client redirect? – James Jun 17 '18 at 23:38
  • @James are you saying I should return the token in the POST response (no res.redirect)? And how do I have the client redirect? – ethanc Jun 18 '18 at 01:08
  • @ethanc yes, return the token in the POST response and then redirect the page from the client - you can redirect by simply setting the `window.location.href` to the destination url – James Jun 18 '18 at 07:36

2 Answers2

1

I have posted this answer elsewhere: Understanding the "post/redirect/get" pattern

but here is the code that works for me:

app.post('/data', function(req, res) {
  data = req.body;
  res.redirect('/db.html');
});
imatwork
  • 523
  • 6
  • 16
0

Based on the info from the comments, you're making an AJAX request. Instead of making the client redirect from server-side, just do it client-side. Here's an example using Axios on the browser (you can do essentially the same thing with AJAX, just messier):

axios.post('/user', { token: 'tokenhere'}).then(function(response) {
    // Status 200 means OK 
    if (response.status === 200) {
        window.location.href = 'user'
    }
})
theob
  • 199
  • 1
  • 10