Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flash messages not deleted when added in context through the onPreResponse extension point #113

Closed
acmoune opened this issue Jul 1, 2017 · 3 comments
Labels
support Questions, discussions, and general support

Comments

@acmoune
Copy link

acmoune commented Jul 1, 2017

I am creating flash messages from some handlers using this code:

request.yar.flash('success', 'Resource created !');

Then in my handlebars layout, I add this:

{{#if flash.success}}<div class="alert alert-success">{{flash.success}}</div>{{/if}}

What is missing is the code that stores the flash messages in the flash template variable.

If for example I want to display the previous flash success message in the '/' route, I get it working when I do this directly in the route handler:

const flashMessages = {
    success: request.yar.flash('success'),
};

return reply.view('index', { flash: flashMessages });

The problems start when I want to do it in onPreResponse extension point. See code below:

server.ext('onPreResponse', (request, reply) => {
      const res = request.response;

      if (res.variety === 'view') {
        if (!res.source.context) res.source.context = {};

        const flashMessages = {
          success: request.yar.flash('success')
        };

        res.source.context.flash = flashMessages;
      }

      reply.continue();
});

So in my handler I can just do this reply.view('index'), and the flash template variable will be automatically set in the onPreResponse extension point.

The problem is that the flash message are not deleted, they are accumulated. The first time it outputs 'Resource created !', the second time it outputs 'Resource created !Resource created !' and so on.

I am unable to find what is wrong here. The only difference between the two methods is the time when I add the flash messages in context. I the first method, the working one, I do it right in the route handler; in the second method, I do it in the onPreResponse extension point. What is yar doing differently between those two moments ?

Please help

@mtharrison
Copy link

mtharrison commented Jul 1, 2017

What is happening here is that your onPreResponse which flushes the flash from your session is being executed after the onPreResponse logic in yar which serializes your session into the cookie in the response.

You might try stating that your extension has a before dependency on yar:

server.ext({
    type: 'onPreResponse',
    method: (request, reply) => {

        const res = request.response;

        if (res.variety === 'view') {
            if (!res.source.context) res.source.context = {};

            const flashMessages = {
                success: request.yar.flash('success')
            };

            res.source.context.flash = flashMessages;
        }

        reply.continue();
    },
    options: {
        before: ['yar']
    }
});

Another point to note is that if the route that sets your flash also renders a view then it will be flushed on that route rather than the next HTTP request, which may or may not be what you want but you should be aware of it. Typically I've seen flash messages set before a redirect to another route.

To answer your question about what is different between the extension and the handler approach we need to look at the flow in your ext approach.

So here's what's happening:

  1. Start | Flash is empty
  2. You set a flash message in some handler | Flash = 'some string'
  3. You make a new HTTP request
  4. Yar's onPreResponse handler looks at your session and sees that Flash = 'some string' so it serializes this as a cookie and sets it in the response
  5. Your onPreResponse handler fetches the flash value and clears it at the same time. However this is too late for it to be persisted in your session (that chance was at 4).
  6. You set a flash message in some handler, this is concatenated to your current flash because you don't specify override | Flash = 'some stringsome string
  7. And so on...

The difference with the example where you get the flash value in the handler is just the order of steps above. You can swap 4 and 5 around. In this case the flash value is correctly cleared before the session is stored in the cookie.

@acmoune
Copy link
Author

acmoune commented Jul 1, 2017

OK, so if I got you right, I have to fetch the flash value before Yar's onPreResponse handler is executed, it is that handler that will notice that the value has been fetched and then empty the cookie.

I just updated my onPreResponse extension point with the before option, and now it works.

Many thanks @mtharrison

@acmoune acmoune closed this as completed Jul 1, 2017
@Marsup Marsup added support Questions, discussions, and general support and removed question labels Sep 21, 2019
@lock
Copy link

lock bot commented Jan 9, 2020

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
support Questions, discussions, and general support
Projects
None yet
Development

No branches or pull requests

3 participants