【发布时间】:2018-07-27 19:08:16
【问题描述】:
我想访问资源标识符包含特殊字符的 Restful API 中的资源。因此,我正在对标识符进行 url_encoding,但在 Mojolicious 中,占位符的自动解码行为不一致。
下面是一个测试脚本,测试一个简单的资源标识符,一个包含空格,一个带加号,一个带斜线。在发送我的请求之前,我对这些中的每一个都进行了 url_encoding,但是第二个由于不同的原因而失败。
#!/usr/bin/env perl
use strict;
use warnings;
use v5.10;
use Data::Dump qw(pp);
use Mojolicious::Lite;
use Mojo::UserAgent;
use Test::Exception;
use Test::More;
use URL::Encode qw(url_encode url_decode);
use WWW::Mechanize;
# Case 1: Access a resource using Standard Placeholders
get '/my/app/standard_placeholder/:id' => sub {
my $c = shift;
my $id_raw = $c->stash('id');
my $id_decoded = url_decode($id_raw);
$c->render( json => { raw => $id_raw, decoded => $id_decoded } );
};
# Shut the server down.
get '/my/api/shutdown' => sub {
exit 0;
};
# Fork for Client and Server
if ( my $pid = fork ) {
note "Waiting for the server to start";
sleep 2;
run_test();
# Clean up server process and we’re done
waitpid( $pid, 0 );
} else {
local @ARGV = qw(daemon);
app->log( Mojo::Log->new( path => "$0.log", level => 'debug' ) );
app->start;
}
exit 0;
### Client
sub run_test {
plan tests => 2;
my $ua = Mojo::UserAgent->new();
my $server_url = 'http://127.0.0.1:3000';
# Standard Placeholders: ([^/.]+)
# Relaxed Placeholders: ([^/]+)
# Wildcard Placeholders: (.+)
subtest 'Standard Placeholders testing url_encoding of route identifiers' => sub {
my @ids = (
"foobar", #
"a space",
"a+plus",
"a/slash",
);
plan tests => 3 * @ids;
for my $id (@ids) {
my $id_encoded = url_encode($id);
my $tx = $ua->get("$server_url/my/app/standard_placeholder/$id_encoded");
SKIP: {
is( $tx->res->code, 200, "Fetch Resource at " . pp($id) )
or skip "Error in response", 2;
is( $tx->res->json->{raw}, $id_encoded, "json->{raw} eq " . pp($id_encoded) );
is( $tx->res->json->{decoded}, $id, "json->{decoded} eq " . pp($id) );
}
}
};
subtest 'Shutdown the server' => sub {
plan tests => 2;
dies_ok {
my $mech = WWW::Mechanize->new( timeout => 3 );
$mech->get("$server_url/my/api/shutdown");
}
'shutdown occurred';
like $@, qr{Error GETing .*?shutdown: Server closed connection without sending any data back},
'detected closed connection';
};
}
1;
还有输出:
mhall@dev19:~$ ./mojo_placeholders.pl
# Waiting for the server to start
Server available at http://127.0.0.1:3000
1..2
# Subtest: Standard Placeholders testing url_encoding of route identifiers
1..12
ok 1 - Fetch Resource at "foobar"
ok 2 - json->{raw} eq "foobar"
ok 3 - json->{decoded} eq "foobar"
ok 4 - Fetch Resource at "a space"
ok 5 - json->{raw} eq "a+space"
ok 6 - json->{decoded} eq "a space"
ok 7 - Fetch Resource at "a+plus"
not ok 8 - json->{raw} eq "a%2Bplus"
# Failed test 'json->{raw} eq "a%2Bplus"'
# at ./mojo_placeholders.pl line 89.
# got: 'a+plus'
# expected: 'a%2Bplus'
not ok 9 - json->{decoded} eq "a+plus"
# Failed test 'json->{decoded} eq "a+plus"'
# at ./mojo_placeholders.pl line 90.
# got: 'a plus'
# expected: 'a+plus'
not ok 10 - Fetch Resource at "a/slash"
# Failed test 'Fetch Resource at "a/slash"'
# at ./mojo_placeholders.pl line 85.
# got: '404'
# expected: '200'
ok 11 # skip Error in response
ok 12 # skip Error in response
# Looks like you failed 3 tests of 12.
not ok 1 - Standard Placeholders testing url_encoding of route identifiers
# Failed test 'Standard Placeholders testing url_encoding of route identifiers'
# at ./mojo_placeholders.pl line 93.
# Subtest: Shutdown the server
1..2
ok 1 - shutdown occurred
ok 2 - detected closed connection
ok 2 - Shutdown the server
# Looks like you failed 1 test of 2.
关于如何解决这个问题的任何建议?
【问题讨论】:
-
我确认这种行为毫无意义。只有未编码的斜杠才有意义,重新编码
+似乎有问题。 (它可能会重新编码以标准化编码以与路径进行比较。我不知道为什么它将编码值放在存储中,但这不是这里的问题。)
标签: perl mojolicious