Perl CGI、query_form、参数的排序与HTTP缓存

后端开发 2026-07-12

最近我遇到一个奇怪的问题,我以为与缓存有关。

在排查问题时,我注意到一个使用query_form来构建一组参数的Perl CGI脚本,生成的参数顺序会改变。

我认为这与Perl的一项最近变更有关,该变更会使哈希键的枚举顺序随机(并非始终相同)。

由于HTTP缓存似乎把不同的URL视为不同的对象,我想要对查询参数有一个稳定的排序。

我该如何做到呢?

代码草图

#...
my $url = URI->new($query->url());
my $url_form;
#...
$url->path($url->path() . 'something');
$url_form = $url->clone();
#...
$url_form->query_form(
    {
        (PN_API_V1_FUNCTION) => API_V1_FN_SEND_FORM,
        (PN_USER_MODE) => $params_ref->{(PN_USER_MODE)},
    });
#...
f(..., $url_form->as_string(), ...)
#...

解决方案

From the documentation of URI::query_form:

$uri->query_form $uri->query_form( $key1 => $val1, $key2 => $val2, ... ) $uri->query_form( $key1 => $val1, $key2 => $val2, ..., $delim ) $uri->query_form( \@key_value_pairs ) $uri->query_form( \@key_value_pairs, $delim ) $uri->query_form( \%hash ) $uri->query_form( \%hash, $delim )

... The form can be set either by passing separate key/value pairs, or via an array or hash reference. Passing an empty array or an empty hash removes the query component, whereas passing no arguments at all leaves the component unchanged. The order of keys is undefined if a hash reference is passed.

所以简单地不要使用哈希引用,而改用列表或列表引用:

$url_form->query_form(
    (PN_API_V1_FUNCTION) => API_V1_FN_SEND_FORM,
    (PN_USER_MODE) => $params_ref->{(PN_USER_MODE)},
);

我认为这是由于Perl的一项最近变更导致哈希键的枚举顺序是随机的(并不总是相同)。

那是 与perl5.18一起的13年前 的事。并不能算是“最近”的。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章