Search code examples
perlhttpsrequestresponsedancer

POST request with Perl and read response object within dancer route


Trying to write the exact equivalence in perl of the following:

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

Unexperienced with perl, this is what I have tried:

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}}]);
};

Solution

  • I take it you are working with Dancer already, or you are adding something to an existing application, and the goal is to hide the POST request to another service behind your API.

    In your curl example, you have the Content-Type application/json, but in your Perl code you are sending a form. That's likely going to be the Content-Type application/x-www-form-urlencoded. It might not be what the server wants.

    In addition to that, you were passing the form data as an array reference, which makes POST believe they are headers. That not what you want.

    In order to do the same thing you are doing with curl, you need a few more steps.

    • You need to convert the data to JSON. Luckily Dancer brings a nice DSL keyword to_json that does that easily.
    • You need to tell LWP::UserAgent to use the right Content-Type header. That's application/json and you can set it either at the request level, or as a default for the user agent object. I'll do the former.
    • In addition to that, I recommend not using HTTP::Request::Common to import keywords into a Dancer app. GET and POST and so on are upper-case and the Dancer DSL has get and post which is lower-case, but it's still confusing. Use HTTP::Request explicitly instead.

    Here's the final thing.

    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
    };