json - 检查 fetch_json 子中的 HTTP 代码/保存以前的输出以在 Perl 中备份
问题描述
所以我必须更新一个 perl 脚本,该脚本通过一个 json 文件,获取名为“items”的键,并将这些项目转换为 perl 输出。
一般来说,我是 Perl/编码的菜鸟,所以请多多包涵。在迭代每个 url 时设置偏移量变量。curl 命令被传递到终端,文件被放入“@lines”数组,最后,任何存储在 $data 中的 json 数据都会被解码和转换。在下面的块中(其中 #populate %manager_to_directs、#populate %user_to_management_chain 和 #populate %manager_to_followers 被注释)是 fetch_json 被调用的地方以及哈希变量从解码的 json 中获取数据的地方。(***如果我对这段代码的解释有误,请随时纠正我)
每次执行该程序时,$cmd 都没有考虑 HTTP 响应,这是一个问题。我只希望当且仅当程序获得 http 200 (OK) 或 http 204 (NO_CONTENT) 时才处理结果,因为程序将运行并且有时会部分刷新我们的 json 端点(来自下面终端的 curl 命令输出中的 url),或者有时甚至根本不刷新。
我所假设的是我可能必须导入 HTTP::Response pragma 并以某种方式将其从 fetch_json 中运行的命令中提取出来,但我不知道从那里去哪里。
我是否必须更新 $cmd 才能提取 http 代码?如果是这样,如果收到 200 或 204 以外的任何内容,我将如何在 fetch_json 子中解释它以退出进程?
哦,还有,我如何将上次执行的先前输出保存在备份文件中?
我能在这里得到的任何帮助将不胜感激!
请参见下面的代码:
从测试运行中提取:
curl -o filename -w "HTTP CODE: %{http_code}\n" --insecure --key <YOUR KEY> --cert <YOUR CERT> https://xxxxxxxxxx-xxxxxx-xxxx.xxx.xxxxxxxxxx.com:443/api/v1/reports/active/week > http.out
#!/usr/bin/env perl
use warnings;
use strict;
use JSON qw(decode_json);
use autodie qw(open close chmod unlink);
use File::Basename;
use File::Path qw(make_path rmtree);
use Cwd qw(abs_path);
use Data::Dumper;
use feature qw(state);
sub get_fetched_dir {
return "$ENV{HOME}/tmp/mule_user_fetched";
}
# fetch from mulesoft server and save local copy
sub fetch_json {
state $now = time();
my ($url) = @_;
my $dir = get_fetched_dir();
if (!-e $dir) {
make_path($dir);
chmod 0700, $dir;
}
my ($offset) = $url =~ m{offset=(\d+)};
if (!defined $offset) {
$offset = 0;
}
$offset = sprintf ("%03d", $offset);
my $filename = "$dir/offset${offset}.json";
print "$filename\n";
my @fields = stat $filename;
my $size = $fields[7];
my $mtime = $fields[9];
if (!$size || !$mtime || $now-$mtime > 24*60*60) {
my $cmd = qq(curl \\
--insecure \\
--silent \\
--key $ENV{KEY} \\
--cert $ENV{CERT} \\
$url > $filename
);
#print $cmd;
system($cmd);
chmod 0700, $filename;
}
open my $fh, "<", $filename;
my @lines = <$fh>;
close $fh;
return undef if !@lines;
my $data;
eval {
$data = decode_json (join('',@lines));
};
if ($@) {
unlink $filename;
print "Bad JSON detected in $filename.\n";
print "I have deleted $filename.\n";
print "Please re-run script.\n";
exit(1);
}
return $data;
}
die "Usage:\n KEY=key_file CERT=cert_file mule_to_jira.pl\n"
if !defined $ENV{KEY} || !defined $ENV{CERT};
print "fetching data from mulesoft\n";
# populate %manager_to_directs
my %manager_to_directs;
my %user_to_manager;
my @users;
my $url = "https://enterprise-worker-data.eip.vzbuilders.com/api/v1/reports/active/week";
while ($url && $url ne "Null") {
my $data = fetch_json($url);
last if !defined $data;
$url = $data->{next};
#print $url;
my $items = $data->{items};
foreach my $item (@$items) {
my $shortId = $item->{shortId};
my $manager = $item->{organization}{manager};
push @users, $shortId;
next if !$manager;
$user_to_manager{$shortId} = $manager;
push @{$manager_to_directs{$manager}}, $shortId;
}
}
# populate %user_to_management_chain
# populate %manager_to_followers
my %user_to_management_chain;
my %manager_to_followers;
foreach my $user (keys %user_to_manager) {
my $manager = $user_to_manager{$user};
my $prev = $user;
while ($manager && $prev ne $manager) {
push @{$manager_to_followers{$manager}}, $user;
push @{$user_to_management_chain{$user}}, $manager;
$prev = $manager;
$manager = $user_to_manager{$manager}; # manager's manager
}
}
# write backyard.txt
open my $backyard_fh, ">", "backyard.txt";
foreach my $user (sort keys %user_to_management_chain) {
my $chain = join ',', @{$user_to_management_chain{$user}};
print $backyard_fh "$user:$chain\n";
}
close $backyard_fh;
# write teams.txt
open my $team_fh, ">", "teams.txt";
foreach my $user (sort @users) {
my $followers = $manager_to_followers{$user};
my $followers_joined = $followers ? join (',', sort @$followers) : "";
print $team_fh "$user:$followers_joined\n";
}
close $team_fh;
my $dir = get_fetched_dir();
rmtree $dir, {safe => 1};
解决方案
因此,如果您想保持 web fetch 和 Perl 处理分离,您可以修改curl
命令,以便通过添加-i
选项在输出中包含响应标头。这意味着必须修改 Perl 以在到达正文之前读取和处理标头。成功的http.out
将如下所示:
HTTP/1.1 200 OK
Server: somedomain.com
Date: <date retrieved>
Content-Type: application/json; charset=utf-8
Content-Length: <size of JSON>
Status: 200 OK
Maybe: More Headers
Blank: Line signals start of body
{
JSON object here
}
不成功的 curl 在 HTTP/1.1 旁边的第一行中将显示 200 OK 以外的内容,因此您可以判断出了问题。
或者,您可以让 Perl 执行实际的 HTTP 获取,而不是依赖 curl;您可以使用LWP::UserAgent或 Perl 中的任何其他 HTTP 客户端库,它们将为您提供整个响应,而不仅仅是正文。
推荐阅读
- authentication - 调用 HttpContext.SignInAsync 后 User.Identity.IsAuthenticated 为 false
- javascript - 如何使用函数或使用 ajax 在 javascript 中执行 curl 命令
- ruby-on-rails - 如何修复 ruby 中丢失的模板配置文件错误
- android - 如何在 Android Studio 中构建旧的 Android 项目
- python - 有没有办法在一个命令而不是 3 个单独的行中指定 matplotlib 图中的 xy 和 z 限制?
- kubernetes - 在没有集群管理员权限的情况下安装 Kubeflow
- apache - htaccess 重定向 301:www 到非 www 不起作用
- typescript - Apollo Server、typescript 和 graphql-modules:graphql_1.parse 不是函数
- azure-iot-hub - 从预配设备上的 UWP 应用获取 Azure IOT Hub 连接字符串
- sql - 删除单行中的重复值