after hook breaks send_file()
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.
participants (1)
-
Warren Young