Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Reading Raw data in CGI::Application

by BaldPenguin (Friar)
on Jan 04, 2007 at 18:43 UTC ( #592993=perlquestion: print w/replies, xml ) Need Help??
BaldPenguin has asked for the wisdom of the Perl Monks concerning the following question:

I have an application using CGI::Application. In this application, one particular aspect is to recieve a POST and process the data, returning the data to the caller. The POST data is in the form of a JSON encoded object and is sent as raw data. When the application recieves the data, somehow it is posted as a param('keyword').

Is this the expected behavior, can I count on it always being received in that param or is there a better way to read raw data using CGI::Application?

Any advice would be helpful.

Update: Found another answer. The server I am using uses CGI v2.89. Starting at v2.92, if CGI detects a content-type other than 'application/x-www-form-urlencoded' or 'multipart/form-data' param processing is stopped and all content is stored in a POSTDATA param. That solved my problem (I think).
jaldhar points this out below.

Everything I've learned in life can be summed up in a small perl script!

Replies are listed 'Best First'.
Re: Reading Raw data in CGI::Application
by derby (Abbot) on Jan 04, 2007 at 19:16 UTC

    That's a feature of CGI - it's treating your post data as an ISINDEX script. Definitely not something you want to rely on:

    #!/usr/local/bin/perl use strict; use warnings; use CGI; use Data::Dumper; my $cgi = CGI->new( '{ "Image": { "Width": 800, "Height": 600, "Title": "View from 15th Floor", "Thumbnail": { "Url": "", "Height": 125, "Width": "100" }, "IDs": [116, 943, 234, 38793] } }' ); print Dumper( $cgi ); $cgi = CGI->new( '{ "Image": { "Width=": 800, "Height": 600, "Title": "View from 15th Floor", "Thumbnail": { "Url": "", "Height": 125, "Width": "100" }, "IDs": [116, 943, 234, 38793] } }' ); print Dumper( $cgi );
    The first dump will show you the JSON data associated with the keyword param. The second dump will show you the hilarity that will ensue if there's an equal signs somewhere in your data.

    Your best bet is to provide a cgi_get_query method that deals with the data how you want to deal with it (as outlined in the docs for CGI::Application).

Re: Reading Raw data in CGI::Application
by jaldhar (Vicar) on Jan 04, 2007 at 21:53 UTC

    To get at the raw data of a post request, use CGI::Applications internal CGI objects special POSTDATA parameter like so:

    my $data = $self->query->param('POSTDATA');


Re: Reading Raw data in CGI::Application
by andyford (Curate) on Jan 04, 2007 at 21:18 UTC

    I've been using the JSON header via CGI::Application::Plugin::JSON to send data from a CGI::Application webapp. Say you have a runmode called "blackout". Here's an untested sketch:

    sub blackout { my $self = shift; my $message = 'hi!'; $self->header_add(-type=>"text/plain"); my $query = $self->query(); my $output = $query->start_html(); $output .= $query->span($message); $self->add_json_header(boStatus=>'OK'); $self->add_json_header(boError=>'SUCCESS'); $self->add_json_header(boMessage=>$message); $output .= $query->end_html; return $output; }
    Notice the span tag: I couldn't find a way to get it working without putting someting in the body of the page, so I just stuck the message in there. Figured it would at least mean something if it ever got displayed by a browser.

    Now on the other end, I'm using the prototype library to get the JSON out of the header.

    I don't know how to do Ajax without prototype, so this is the best I can give you.

    function tryJSON(app) { var url = '/cgi-bin/TryCGIApp.cgi'; var params = "mode=blackout"; new Ajax.Request(url, { onSuccess : function(resp,jsonheader) { var foo = jsonheader.boStatus; var funk = jsonheader.boError; alert("The response from the server is: " + foo + " and " ++ funk); }, onFailure : function(resp) { alert("Oops, there's been an error."); }, parameters : params }); }

    I assume there's some way to reverse this process, with the javascript adding the JSON headers, but I haven't gotten that far yet...If you get it, please post!

    Update:  explicitly mention CGI::Application::Plugin::JSON

    non-Perl: Andy Ford

      ++ and thanks for the clue about CGI::Application::Plugin::JSON (I hadn't seen that). I've been using JSON but instead of header type text/plain, I've been using application/json (which is outlined in the rfc).

        Quick solution <if anybody still needed on sending json for runmode>
        sub send_json_data: Runmode { my $self = shift; $self->header_add(-type=>"application/json"); ... }
        OR refer this inside of CGI::Application::Plugin::JSON import() >> _send_headers() should take care of it.. though, its not taking care of for above runmode to return json data.
        sub _send_headers { my $self = shift; my $private = $self->param('__CAP_JSON') || {}; if( defined $private->{header} ) { $self->header_add( '-x-json' => $self->json_header_string ); } if( defined $private->{json_body} ) { $self->header_add('-type' => 'application/json'); } elsif ( defined $private->{json_callback} ) { $self->header_add('-type' => 'text/javascript'); } }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://592993]
Approved by Corion
Front-paged by andyford
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (10)
As of 2017-05-25 18:47 GMT
Find Nodes?
    Voting Booth?