http://qs321.pair.com?node_id=1214447

morgon has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I have a (flat) zip-file containing htmls, pngs and jpgs that I want to serve as a website.

I started out with plain psgi, where it was really simple.

Now I want to move to Dancer2 and I seem to have a problem with encodings.

The html-files in the zip are utf-8 and I am using Archive::Zip to read it, so in the psgi-version I did something like

return [200, [ "Content-Type" => "text/html; charset=utf-8"], [ $membe +r->contents ] ];
And that worked.

Now I try to do the same thing in Dancer2 like this:

use strict; use Dancer2; use Archive::Zip; any '/**' => \&handler; sub handler { my($context)=@_; my $zip = Archive::Zip->new; $zip->read("eco.zip") == Archive::Zip::AZ_OK or die "cannot read z +ip\n"; my $path = $context->request->path; $path =~ s|^/||; my $member = $zip->memberNamed($path) or die "no such member: $pat +h\n"; my $type; $type = "text/html; charset=utf-8" if $path =~ /\.html$/; $type = "image/jpg" if $path =~ /\.jpg$/; $type = "image/png" if $path =~ /\.png$/; die "unhandled file: $path\n" unless $type; response_header "Content-Type" => $type; return $member->contents; }; start;
And while it somewhat works (the header seeems to be sent just fine) accented characters look wrong in the browser.

Does anyone have an idea what this could be?

Also I am t a total newbie to Dancer, so I would greatly appreciate any better ways to do this in Dancer as I suppose this is not a very idiomatic way to do this.

Many thanks!

Replies are listed 'Best First'.
Re: serving a zip file with Dancer2
by 1nickt (Canon) on May 14, 2018 at 14:27 UTC

    Hi, just a guess: do you have the charset set in your config?

    charset: UTF-8
    If so, the output may be getting double-encoded since you add a charset manually in your Content-Type header?

    As for idiomatic, I don't work with compressed files myself but I can say that middlewares are ususally the right approach to this type of intermediate content handling, see eg Plack::Middleware::Deflater (which compresses outgoing content).

    Hope this helps!


    The way forward always starts with a minimal test.
      Yes, some double-encoding is what I suspect.

      But I don't use a config at the moment - it's just a script that I run via plackup.

      I have tried to add

      config->{charset} = "UTF-8";
      to the script but that does not change anything.

      I guess the problem is that I need to tell Dancer that the content I get from the zip-file is already encoded but I can't figure out how.

      I currently try to use a Dancer2::Core::Response-object but I can't make that work at all...

Re: serving a zip file with Dancer2
by morgon (Priest) on May 14, 2018 at 15:05 UTC
    I can get it to work if I change
    return $member->contents;
    to this:
    return $type =~ /^text/ ? decode_utf8($member->contents) : $member->contents;
    But this is really ugly.

    What is the proper way to do this?

Re: serving a zip file with Dancer2
by Anonymous Monk on May 14, 2018 at 17:37 UTC
    Start by using a browser-side debugger to s-e-e what the HTML response including headers actually looks like when it finally arrives.

      Could you recommend your favorite "browser-side debugger" and give us pointers for how you would use it in this case? The more specific, the more helpful.

      I did.

      And the headers were ok - they were identical to the psgi-version.

      The problem (as I mentioned in another post) seems to be that while a plain psgi-app returns happily whatever you give it, Dancer seems to be a little cleverer which in this case gets in my way.

      I need to explicitly decode the string as utf-8 to keep Dancer from encoding it again then it works.

      I would be very interesting to learn if this is the proper way to do this though...