[dancer-users] after hook breaks send_file()
Warren Young
warren at etr-usa.com
Mon Mar 24 13:26:01 GMT 2014
Part of the web app I'm porting to Dancer builds dynamic PDF files for
the client when they hit certain URLs. I'm generating these files in
the route handler, then calling Dancer::send_file() at the end of the
route handler.
All of this is working fine, except that I was getting a 500 error on
the send_file call:
[8802] error @0.035479> [hit #16]request to GET /pdf/foo.pdf crashed:
Too late to set another cookie, headers already built at
/usr/lib/perl5/site_perl/5.8.8/Dancer/Response.pm line 166. in
/usr/lib/perl5/site_perl/5.8.8/Dancer/Handler.pm l. 98
After some debugging, I found that all it takes to cause this is to add
this to a freshly-generated lib/myapp.pm:
hook after => sub {
my $sid = session->id;
};
That's it, merely *accessing* the session object after send_file() is
called causes the error.[*]
I was able to fix this by putting this at the top of the after hook:
return if request->path =~ m{\.pdf$};
I'm not sure if this creates a backdoor to my app's dynamic PDFs or not,
bypassing session management. My initial thought is that it doesn't,
but data security can be tricky, and requires more thought than I've
been able to give this so far.
Bottom line, is there any good reason why my after hook should not be
able to a) check the Dancer session object; and b) redirect the user to
another page, even though we've already scheduled a file download?
[*] My actual "after" hook code is more involved, checking whether our
back-end server marked this session ID as invalid. If it is, I redirect
the user to '/' to make them log back in again. I do this in the
"after" hook because it isn't until after I try talking to the back-end
server that I learn whether it still believes we're logged in. Putting
this in the "after" hook satisfies the DRY principle, since a worse
alternative is to wrap all back-end server calls with "are we still
alive?" checks. Another poor alternative is to "ping" the back-end
server in the "before" hook, but that's wasteful and creates a race
condition.
More information about the dancer-users
mailing list