jdorwin has asked for the wisdom of the Perl Monks concerning the following question:

Howdy

Expected output is a bearer token that looks kind of like 49vh29378bhwbejgmhm95.

This worked yesterday, but I guess I touched it wrong and now it gives me "Use of uninitialized value in print at ./rough.pl line 93." Line 93 is the line that has print getToken(); on it. The command between the ticks (``) works in my terminal, and returns the JSON output with a token in it. I can't seem to figure out why I'm getting this error. Am I missing something?

sub getToken # generates Bearer access token { my $output = `curl -k -s -XPOST (URL) -dgrant_type=password -dclie +nt_id=(client ID) -dclient_secret=(client secret) -dusername=(usernam +e) -dpassword=(password)`; $output =~ /"access_token":"(.*)", "ex/g; return $1; } print getToken();
Any help is greatly appreciated!

Replies are listed 'Best First'.
Re: why is this an uninitialized value?
by Corion (Patriarch) on Jun 29, 2018 at 15:01 UTC
    $output =~ /"access_token":"(.*)", "ex/g;

    You never check if the output really matches.

    Most likely, if you check, then you find that it doesn't match:

    $output =~ /"access_token":"(.*)", "ex/g or die "Couldn't find access token in [[$output]]";

    But maybe you really do want to parse the output in a better way, since it seems as if the output could be JSON:

    use JSON 'decode_json'; # or JSON::XS , or JSON::Tiny ... sub getToken { my $output = `curl -k -s -XPOST (URL) -dgrant_type=password -dclie +nt_id=(client ID) -dclient_secret=(client secret) -dusername=(usernam +e) -dpassword=(password)`; my $decoded_output = decode_json( $output ); die "Couldn't find access token in [[$output]]" unless $decoded_output->{access_token}; return $output->{access_token} }
Re: why is this an uninitialized value?
by stevieb (Canon) on Jun 29, 2018 at 15:04 UTC

    I suspect that it's due to the fact that $output doesn't contain what you think it does, and the return ($1) is uninitialized.

    Better to check for this condition (untested):

    sub getToken { my $output = `curl -k -s -XPOST (URL) -dgrant_type=password -dclie +nt_id=(client ID) -dclient_secret=(client secret) -dusername=(usernam +e) -dpassword=(password)`; if ($output =~ /"access_token":"(.*)", "ex/g){ return $1; } else { die "output not as expected...\n"; } }
Re: why is this an uninitialized value?
by davido (Cardinal) on Jun 29, 2018 at 17:25 UTC

    Here's how I would have posted the code sample for this question to make it easier to answer:

    my $output = q/..../; my $matched = $output =~ m/"access_token":"(.*)", "ex/g; print "Match: $matched\n"; say '$1 is <', (defined($1) ? $1 : 'undef'), ">\n";

    Except in place of .... I would paste in exactly the output from the curl call, but paired down to enough to demonstrate the portion you're trying to match without showing us 64kb of extra cruft.

    When you do this, you will probably be able to answer the question yourself without even posting it, because you will see exactly why the match is failing.

    But it's also probable that when you solve this problem, by retaining a regex approach you'll remain quite fragile. JSON isn't really intended to be processed as plain old text. And your regular expression is expecting the next key after "access_token" to start with "ex.

    According to the JSON spec, "An object is an unordered set of name/value pairs." There's no guarantee of key order when objects are serialized and deserialized. That being the case, the match could fail while the data remains perfectly valid if you somehow got the keys back in a different order. There is no inherent order to hash keys, even in JSON. If you rely on an order, you're relying in an implementation detail that may work in practice but only works because nothing has changed to cause keys to come in some other order. Order is not guaranteed by the spec.

    A far better approach would be to process the JSON as JSON using JSON to decode it. Then you could just dive into the datastructure precisely, and without any regex.


    Dave

      That point can’t be emphasized enough:   treat JSON as a “black-box string.”   Use established libraries to encode it, then use established libraries on the other end to decode it.   Don’t look at it, or try to roll your own.   (And the same is true of XML and YAML.)

        That point can’t be emphasized enough:

        That was too much. Its stinks. Flush it.™

A reply falls below the community's threshold of quality. You may see it by logging in.