Reputation: 61
I've been working building an emulator in Perl and one of the issues I'm facing is parsing JSON files located in the computer. When I try fetching them from my server, they work fine...
method getContent(\@arrURLS) {
my %arrInfo;
my $resUserAgent = Mojo::UserAgent->new;
foreach my $strURL (@arrURLS) {
$resUserAgent->get($strURL => sub {
my($resUserAgent, $tx) = @_;
if ($tx->success) {
my $strName = basename($strURL, '.json');
my $arrData = $tx->res->body;
$arrInfo{$strName} = $arrData;
}
Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;
}
return \%arrInfo;
}
Let's assume @arrURLS
is:
my @arrURLS = ("file:///C:/Users/Test/Desktop/JSONS/first.json", "file:///C:/Users/Test/Desktop/JSONS/second.json");
The above url's are the one's that aren't working, however if I change that to:
my @arrURLS = ("http://127.0.0.1/test/json/first.json", "http://127.0.0.1/test/json/second.json");
it works.
Also I would like to use something better than Mojo::UserAgent
because it seems a bit slow, when I was using Coro
with LWP::Simple
it was much faster but unfortunately Coro
is broken in Perl 5.22...
Upvotes: 3
Views: 412
Reputation: 63892
Myself using WWW::Mechanize for all such tasks. From the doc:
WWW::Mechanize is a proper subclass of LWP::UserAgent and you can also use any of LWP::UserAgent's methods.
what means you can feed it with file://
type URLs too.
For example, the following one-liner dumps your passwd
file.
perl -MWWW::Mechanize -E 'say WWW::Mechanize->new->get("file://etc/passwd")->content'
or an example without any error handling...
use 5.014;
use warnings;
use WWW::Mechanize;
my $mech = WWW::Mechanize->new;
$mech->get('file://some/path');
say $mech->content;
Anyway, probably is better to use for local files some file-based
utility, myself using for all file-things the Path::Tiny module, which has (not limited only) an method for file slurping, such:
use Path::Tiny;
my $content = path('/some/path')->slurp;
or just plain perl:
open my $fh, '<', '/some/file' or die "...";
my $content = do { local $/; <$fh> };
close $fh;
Upvotes: 2
Reputation: 126722
It's important always to say what additional modules you're using. I think your code uses Method::Signatures
, and I've tested the code below only to check that it compiles with that module in place
Mojolicious is an excellent tool for its purpose, but it is focused on HTTP URLs. LWP::UserAgent
is much more general-purpose, and the documentation for LWP
says this
Provides an object oriented model of HTTP-style communication. Within this framework we currently support access to http, https, gopher, ftp, news, file, and mailto resources
Your method becomes something like this. It's untested
method get_content(\@urls) {
my %info;
my $ua = LWP::UserAgent->new;
for my $url (@urls) {
my $res = $ua->get($url);
die $res->status_line unless $res->is_success;
my $name = basename($url) . '.json';
my $data = $res->decoded_content;
$info{$name} = $data;
}
\%info;
}
I would also encourage you to drop Hungarian notation in the context of Perl code, as the language already has its sigils that denote the data type
@arrURLS
duplicates the information that this arrURLS
is an array, while %arrInfo
is just wrong as this arrInfo
is a hash. $arrData
is actually a scalar, although perhaps some indicator that it is also a reference may help, and $arrURLS[0]
is also a scalar (hence the dollar)
There is also nothing to stop you using $arrURLS
(which is a completely separate variable from @arrURLS
)
Upvotes: 1
Reputation: 54323
User Agents are mainly for downloading files through http. They are usually not expected to handle filesystem URIs. You need to open
and read the file yourself, or use a module like File::Slurp that does it for you.
It could look something like this.
use File::Slurp 'read_file';
method getContent(\@arrURLS) {
my %arrInfo;
my $resUserAgent = Mojo::UserAgent->new;
foreach my $strURL (@arrURLS) {
if (substr($strURL, 0, 4) eq 'file') {
$arrInfo{basename($strURL, '.json')} = read_file($strURL);
} else {
$resUserAgent->get($strURL => sub {
my($resUserAgent, $tx) = @_;
if ($tx->success) {
my $strName = basename($strURL, '.json');
my $arrData = $tx->res->body;
$arrInfo{$strName} = $arrData;
}
Mojo::IOLoop->stop;
});
Mojo::IOLoop->start;
}
}
return \%arrInfo;
}
Upvotes: 4