使用Perl的POST请求和在舞者路线中读取响应对象

时间:2016-09-26 14:53:21

标签: perl https request response dancer

尝试在perl中写出以下完全等价:

curl -H "Content-Type: application/json" -X POST -d '{"user": { "uid":"13453"},"access_token":"3428D3194353750548196BA3FD83E58474E26B8B9"}' https://platform.gethealth.io/v1/health/account/user/

对perl没有经验,这就是我的尝试:

use HTTP::Request::Common;
use LWP::UserAgent;

get '/gethealthadduser/:id' => sub {
  my $ua = LWP::UserAgent->new;
  $ua->request(POST 'https://platform.gethealth.io/v1/health/account/user', [{"user": { "uid":param("id")},"access_token":config->{gethealthtoken}}]);
};

3 个答案:

答案 0 :(得分:1)

我认为您已经与Dancer合作,或者您正在向现有应用程序添加内容,目标是将POST请求隐藏到API后面的其他服务。

在curl示例中,您有Content-Type application/json,但在您的Perl代码中,您正在发送表单。这可能是内容类型application/x-www-form-urlencoded。它可能不是服务器想要的。

除此之外,您将表单数据作为数组引用传递,这使得POST认为它们是标题。那不是你想要的。

为了做与卷曲相同的事情,你需要更多的步骤。

  • 您需要将数据转换为JSON。幸运的是,舞者带来了a nice DSL keyword to_json,这很容易做到。
  • 您需要告诉LWP :: UserAgent使用正确的Content-Type标头。那个application/json你可以在请求级别设置它,或者作为用户代理对象的默认设置。我会做前者。
  • 除此之外,我建议不要使用HTTP :: Request :: Common将关键字导入Dancer应用程序。 GETPOST等等是大写的,而舞者DSL有getpost这是小写的,但它仍然令人困惑。请明确使用HTTP::Request

这是最后的事情。

use LWP::UserAgent;
use HTTP::Request;

get '/gethealthadduser/:id' => sub {
    my $ua  = LWP::UserAgent->new;
    my $req = HTTP::Request->new(
        POST => 'https://platform.gethealth.io/v1/health/account/user',
        [ 'Content-Type' => 'application/json' ],                                   # headers
        to_json { user => param("id"), access_token => config->{gethealthtoken} },  # content
    );

    my $res = $ua->request($req);

    # log the call with log level debug
    debug sprintf( 'Posted to gethealth.io with user %s and got a %s back.', 
        param('id'), 
        $res->status_line
    );

    # do things with $res
};

答案 1 :(得分:1)

尝试使用HTTP :: Tiny(它在CPAN上)。恕我直言,它比LWP :: UserAgent更清晰,但后者更受欢迎。

这里有一些应该开箱即用的代码:

use HTTP::Tiny 0.064;  # use a recent version or better

my $url = 'https://api.somewhere.com/api/users';
my $data = {
  first_name => "joe",
  last_name => "blow"
  };
my $method = 'POST';


my $default_headers = {
  'Authorization' => "Bearer ".$token,  # if needed
  'Accept' => 'application/json'
  };

my $tiny = HTTP::Tiny->new(
  agent => 'mywebsite.com',
  default_headers => $default_headers,
  timeout => 30
  );

my $response;
if ( ($method eq 'POST') || ($method eq 'PUT') ) {
  $response = $tiny->request($method, $url, {
    headers => {
      'Content-Type' => 'application/json'
      },
    content => &toJSON($data)
    });
  }
 else {
  if ($data) {
    die "data cannot be included with method $method"; }
  $response = $tiny->request($method, $url); 
  }

die unless $response->{'success'};

祝你的项目好运!

答案 2 :(得分:0)

以下是具有正确格式和已发布参数结构的解决方案:

get '/api/gethealthadduser/:id' => sub {
    my %user = (
        uid  => param("id")
    );
    # my $user = {
    #     uid  => param("id")
    # };

    my $ua  = LWP::UserAgent->new;
    my $req = HTTP::Request->new(
        POST => 'https://platform.gethealth.io/v1/health/account/user/',
        [ 'Content-Type' => 'application/json' ],                                   # headers
        JSON::to_json({ user => \%user, access_token => config->{gethealthtoken} })  # content
    );
    my $res = $ua->request($req);
    print STDERR Dumper($res);
    $res;
};