Perl 无法解释的字符串升级为utf-8

Perl 无法解释的字符串升级为utf-8,perl,http,unicode,utf-8,poe,Perl,Http,Unicode,Utf 8,Poe,我有一个带有POE的Perl web服务器。在数据到达连接之前,在POE::Filter::HTTPD->put中连接头和体。出于某些bizare原因,一些头被提升为utf-8,这意味着二进制体正在被破坏 问题在于,头中的join_as_strings()正在将某些头升级为UTF-8,即使它不应该升级。例如,如果我添加以下代码,则只有最后一行生成警告。因此,3个非utf8字符串的联接将生成一个UTF-8字符串,但不是所有的头。解决方案是对$ret[-1]进行utf8::降级,但我想知道为什么会发

我有一个带有POE的Perl web服务器。在数据到达连接之前,在POE::Filter::HTTPD->put中连接头和体。出于某些bizare原因,一些头被提升为utf-8,这意味着二进制体正在被破坏

问题在于,头中的join_as_strings()正在将某些头升级为UTF-8,即使它不应该升级。例如,如果我添加以下代码,则只有最后一行生成警告。因此,3个非utf8字符串的联接将生成一个UTF-8字符串,但不是所有的头。解决方案是对$ret[-1]进行utf8::降级,但我想知道为什么会发生这种情况

my $vnl = _process_newline( $value, $endl );
warn "$$: '$name' is utf8" if utf8::is_utf8( $name );
warn "$$: '$sep' is utf8" if utf8::is_utf8( $sep );
warn "$$: '$vnl' is utf8" if utf8::is_utf8( $vnl );
push @ret, join $sep, $name, $vnl;
# only this last line produces a warning
warn "$$: the join has utf8 " if utf8::is_utf8( $ret[-1] );

简而言之,Perl将在没有警告的情况下将字符串升级为utf-8。我使用的是一个MIME::Type对象,我认为它是一个字符串。MIME::Types用open DB打开它的DB,“
is_utf8
只告诉您是否为字符串设置了Perl的内部标志。不要在代码中使用它。代码的作者应该总是知道他们操作的字符串是包含字节还是代码点。对于“一些头被提升为utf-8”,Perl可以自由使用它想要的任何内部存储格式。这不会改变字符串。如果您使用
eq
来比较原始字符串和它的升级/降级版本,它将返回true。Re“解决方案是在$ret[-1]上进行utf8::降级”,当代码根据字符串的内部存储格式(由
返回的值是\u utf8
)对字符串进行不同的处理时,我们说它存在Unicode错误
utf8::降级
utf8::升级
被用作此类错误的解决方法。关于“我想知道为什么会发生这种情况”,请提供
use Devel::Peek的输出;$name、$sep、$vnl、$ret[-1]的转储($)
(在
推送之后
)。是的,不应该使用
字节
Re“简短的回答是Perl将在没有警告的情况下将字符串升级为utf-8。”,是的,但我想不出Perl会无缘无故地升级格式的情况。毕竟,降级格式更有效。因此,Perl只在必要时升级,更长远的说法是,我是从MIME::Types获取内容类型的,它使用:encoding(utf-8)读取其DB。当POE::Filter::HTTPD在该值上运行utf8::downgrad()时,headers+body的最终连接仍在将其全部升级为UTF-8。这是在混为一谈<代码>:编码(UTF-8)与内部存储格式无关<代码>utf8::降级仅修改内部存储格式。您应该回答的唯一问题是:sub需要解码文本(也称为Unicode码点字符串)还是编码文本(字节)。您不必关心内部存储格式。如果必须这样做,这意味着代码有缺陷。因此,要么你在传递编码文本时传递了解码文本(这与
is_utf8
降级
升级
)无关),因此子模块中存在错误,要么两者都有。听起来像是你传递了解码的文本,而sub使用
使用字节。我认为HTTP头是纯ASCII的。如果您生成的只是ASCII码,那么您实际上提供了编码文本,因此这纯粹是模块中的一个bug。
是否正确并不重要。