Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

json return value

by stenasc (Novice)
on Jul 11, 2013 at 08:25 UTC ( [id://1043651]=perlquestion: print w/replies, xml ) Need Help??

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

First of all, this is my first post but I have been reading around here first trying to find a solution. Secondly, I haven't a clue about json. I'm an embedded C programmer with limited perl experience. Basically I want to send a simple string of json containing two parameters using a post command to a website and get an integer response. I used the following code that I found on this site as the server saved as a cgi file in the cgi-bin directory of the web server. The webserver is Apache. Do I need to install anything on the webserver to handle json or is it handled by default?

#!/usr/bin/env perl use strict; use warnings; use CGI (); use JSON (); my $q = CGI->new; my $json = JSON->new->utf8; my $input = $json->decode( $q->param('POSTDATA') ); my $a = $input->{a}; my $b = $input->{b}; my $c = $a + $b; print $q->header("application/json"); print $json->encode({ c => $c });

The following, I used as client...

#!/usr/bin/env perl use strict; use warnings; use JSON (); use LWP::UserAgent (); use HTTP::Request::Common qw( POST ); my $data = { a => 40, b => 2 }; my $json = JSON->new->utf8; my $ua = LWP::UserAgent->new; my $req = POST( "http://myurl/public_html/cgi-bin/json-addition.cgi", Content_Type => 'application/json', Content => $json->encode($data), ); my $result = $json->decode( $ua->request($req)->decoded_content ); print $result->{c}, "\n";

I get the following response malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "Can't connect to myurl...") at json-client.pl line 21. As you can see fellow monks, I am an ignorant soul and need your salvation. Please enlighten me with some of your wisdom?

Replies are listed 'Best First'.
Re: json return value
by tobyink (Canon) on Jul 11, 2013 at 08:37 UTC

    You're not checking whether the response is an HTTP success...

    my $req = POST( "http://myurl/public_html/cgi-bin/json-addition.cgi", Content_Type => 'application/json', Content => $json->encode($data), ); my $response = $ua->request($req); $response->is_success or die($response->status_line); my $result = $json->decode($response->decoded_content); print $result->{c}, "\n";
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
      I believe LWP can also return is_success=true + X-Died header https://github.com/libwww-perl/libwww-perl/issues/46 (but probably not related to OP code ), and also return truncated responses https://rt.cpan.org/Public/Bug/Display.html?id=85759

      I give up on this json/perl stuff. The cgi stuff looks as if it just responds to html pages not anything else and with not having permission to access cgi files, its just too difficult. All I want is to send an integer to a website from a standalone perl client using post and get an integer returned. Is it that difficult? Embedded development is easy compared to this. I'm beginning to lose my belief in this Perl religion !! I think I'll stick to the C sinners club.

        It's really not that difficult...

        Server

        use v5.14; use CGI (); use JSON::PP (); my $q = 'CGI'->new; my $json = 'JSON::PP'->new; my $input = $json->decode( $q->param('POSTDATA') ); my $a = $input->{a}; my $b = $input->{b}; my $c = $a + $b; print $q->header("application/json"); print $json->encode({ c => $c });

        Client

        use v5.14; use HTTP::Tiny (); use JSON::PP (); my $json = 'JSON::PP'->new; my $http = 'HTTP::Tiny'->new; my $url = 'http://buzzword.org.uk/2013/json-addition.cgi'; my $input = { a => 40, b => 2 }; my @request = ($url => { content => $json->encode($input) }); my $response = $http->post(@request); my $output = $json->decode($response->{content}); say $output->{c};

        (All modules used above are part of Perl core as of 5.14+, but CGI is scheduled to leave core in a future version of Perl.)

        package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: json return value
by Corion (Patriarch) on Jul 11, 2013 at 08:38 UTC

    Have you looked at the status code and the content of your response?

    my $res= $ua->request($req); print $res->is_success ? "yay\n" : "error\n"; print sprintf "Status %d\n", $res->code; print $res->decoded_content;

    Maybe the module is correct and you don't actually get JSON back, but an error message that starts with Can't connect to myurl....

Re: json return value
by marto (Cardinal) on Jul 11, 2013 at 08:42 UTC

    The first thing I'd do is to ensure your server script runs without problems, perhaps you don't have the JSON module installed, perl does not have JSON as part of it's core module set. Running the script from the command line will throw errors if a module is missing, apache will throw an error and your client won't be able to get a valid response. Various debugging techniques are covered in CGI Help Guide from CGI Programming.

    Update: to install JSON from the command prompt:

    cpan JSON

    Or speak to your systems administrator.

      "perl does not have JSON as part of it's core module set"

      True, but recent versions of Perl do have JSON::PP, which provides an almost identical API. The OP could consider switching to that if he doesn't have JSON and doesn't want to install it.

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

        Apologies, You are correct. I was going by core modules listed on http://perldoc.perl.org, as I didn't have perl installed on the machine I was posting from at the time.

        Update: This seems to be a problem. I'll investigate further and report the issue with the documentation maintainers.

        I don't see this listed as a core module as of 5.18, perhaps some distributions of Perl do have this as they tend to package non core modules and among other things.

        Update: fixed typo.

        Hi, Thanks to all that replied. Just found out that the web hosts cannot install json as the website is on a shared server. However JSON::PP looks to be installed. I'm unsure of the changes that need to be made in the server and client code to ensure it works with JSON::PP. Any help greatly appreciated.

Re: json return value
by Anonymous Monk on Jul 11, 2013 at 08:43 UTC

    Do I need to install anything on the webserver to handle json or is it handled by default?

    What does that mean? Its all just bytes / http, so what further handling are you talking about?

    Try

    #!/usr/bin/env perl -- use strict; use warnings; use JSON (); use WWW::Mechanize 1.72; Main( @ARGV ); exit( 0 ); sub Main { my $data = { a => 40, b => 2 }; my $json = JSON->new->utf8; my $ua = WWW::Mechanize->new; $ua->post( "http://myurl/public_html/cgi-bin/json-addition.cgi", Content_Type => 'application/json', Content => $json->encode($data), ); $ua->res->dump; if( $ua->is_json ){ my $result = $json->decode( $ua->content ); print $result->{c}, "\n"; } } sub WWW::Mechanize::is_json { int( 'application/json' eq $_[0]->ct ) }

    General notions you should be aware of as well as lists of things to check are found in Coping with Scoping , CGI to mod_perl Porting. mod_perl Coding guidelines , brian's Guide to Solving Any Perl Problem, CGI Help Guide , Troubleshooting Perl CGI scripts , On debugging, verify everything, talk to teddybear ...

    Looks to me like /public_html/ is something extra you don't need

      is_json is like is_html, one trick pony :)

      use MIME::Types; our $mimetypes = MIME::Types->new; sub WWW::Mechanize::is_mimetype { goto &WWW::Mechanize::is_mt } sub WWW::Mechanize::is_mt { $mimetypes->mimeTypeOf( $_[1] )->equals( $ +_[0]->ct ) }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1043651]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (3)
As of 2024-03-29 02:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found