Как сделать Mason2 UTF-8 чистый?

Переформулируя вопрос, потому что

Комментарий: Этот вопрос уже получил «значок популярного вопроса», так что, вероятно, я не единственный безнадежный человек. :)

К сожалению, демонстрация полного стека задач приводит к очень длинному вопросу, и он очень специфичен для Мейсона .

Во-первых, Поэт и Мейсон являются наиболее продвинутыми фреймворками в CPAN. Ничего похожего не нашел, что из коробки позволяет писать такие чистые / но очень хакерские :) / web-apps, со многими включенными батареями (ведение журнала, кеширование, управление конфигурациями, на основе PGSI и т. д.)

К сожалению, автора не волнует остальное слово, например, по умолчанию он основан только на ascii, без какого-либо руководства, часто задаваемых вопросов или советов по поводу: как использовать его с юникодом

Теперь факты. Демо. Создайте приложение для поэта:

poet new my #the "my" directory is the $poet_root
mkdir -p my/comps/xls
cd my/comps/xls

и добавьте в dhandler.mc следующее (которое продемонстрирует две основные проблемы)

<%class>
    has 'dwl';
    use Excel::Writer::XLSX;

<%init>
    my $file = $m->path_info;

    $file =~ s/[^\w\.]//g;
    my $cell = lc join ' ', "ÅNGSTRÖM", "in the", $file;

    if( $.dwl ) {
        #create xlsx in the memory
        my $excel;
        open my $fh, '>', \$excel or die "Failed open scalar: $!";
        my $workbook  = Excel::Writer::XLSX->new( $excel );
        my $worksheet = $workbook->add_worksheet();
        $worksheet->write(0, 0, $cell);
        $workbook->close();

        #poet/mason output
        $m->clear_buffer;
        $m->res->content_type("application/vnd.ms-excel");
        $m->print($excel);
        $m->abort();
    }

<% $cell %>
download <% $file %>

и запустите приложение

../bin/run.pl

перейдите по адресу http: / /0:5000/xls/hello.xlsx, и вы получите:

+----------------------------+
| ÅngstrÖm in the hello.xlsx |
+----------------------------+
download hello.xlsx

Щелкнув загрузку hello.xlsx , вы получите hello.xlsx в загрузках.

Сказанное выше демонстрирует первую проблему, например, источник компонента не находится "под" используйте utf8; , поэтому lc не понимает символы.

Вторая проблема заключается в следующем, попробуйте [ http: // 0: 5000 / xls / hélló.xlsx] или http: // 0: 5000 / xls / h% C3% A9ll% C3% B3.xlsx и вы увидите:

+--------------------------+
| ÅngstrÖm in the hll.xlsx |
+--------------------------+
download hll.xlsx
#note the wrong filename

Конечно, вход ( path_info ) не декодируется, сценарий работает с октетами в кодировке utf8, а не с символами Perl.

Итак, говоря perl - "источник находится в utf8", добавляя use utf8; в , получаем

+--------------------------+
| �ngstr�m in the hll.xlsx |
+--------------------------+
download hll.xlsx

добавление функции use 'unicode_strings' (или используйте 5.014; ) еще хуже:

+----------------------------+
| �ngstr�m in the h�ll�.xlsx |
+----------------------------+
download h�ll�.xlsx

Конечно , источник теперь содержит широкие символы, ему требуется Encode :: encode_utf8 на выходе.

Можно попробовать использовать такой фильтр:

<%filter uencode><% Encode::encode_utf8($yield->()) %>

и отфильтровать весь вывод:

% $.uencode {{
<% $cell %>
download <% $file %> % }}

, но это помогает только частично, потому что нужно позаботиться о кодировке в или блоков. Кодирование / декодирование внутри кода Perl во многих местах ( читается: не на границах ) приводит к нечеткому коду.

Кодирование / декодирование должно выполняться четко где-то в Поэт / Мейсон границы - конечно, Плак работает на байтовом уровне.


Частичное решение.

К счастью, Поэт умно позволяет изменять это части (и Мэйсона), так что, в каталоге $ поэта / lib / My / Mason вы можете изменить Compilation.pm на:

override 'output_class_header' => sub {
    return join("\n",
        super(), qq(
        use 5.014;
        use utf8;
        use Encode;
        )
    );
};

что будет вставлять нужную преамбулу в каждый компонент Mason . (Не забудьте прикоснуться к каждому компоненту или просто удалить скомпилированные объекты из $ poet_root / data / obj ).

Также вы можете попробовать обработать запрос / ответы на границы, отредактировав $ pet_root / lib / My / Mason / Request.pm на:

#found this code somewhere on the net
use Encode;
override 'run' => sub {
    my($self, $path, $args) = @_;

    #decode values - but still missing the "keys" decode
    foreach my $k (keys %$args) {
        $args->set($k, decode_utf8($args->get($k)));
    }

    my $result = super();

    #encode the output - BUT THIS BREAKS the inline XLS
    $result->output( encode_utf8($result->output()) );
    return $result;
};

Кодировать все - неправильная стратегия, она нарушает например, XLS.

Итак, 4 года спустя (я задал исходный вопрос в 2011 году) все еще не знаю :( как правильно использовать юникод в приложениях Mason2 и до сих пор не существует документации или помощники по этому поводу.: (

Основные вопросы: - где (какие методы должны быть изменены модификаторами метода Moose) и как правильно декодировать входы и где выход (в приложении Poet / Mason.)

  • , но только текстовые, например text / plain или text / html и тому подобное ...
  • a выполните вышеуказанное «без сюрпризов» - например, то, что будет просто работать. ;)

Может ли кто-нибудь помочь с реальным кодом - что я должен изменить в приведенном выше?

23
задан Community 23 May 2017 в 12:00
поделиться