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

I've been programming in PERL now for quiet a while but I've come across a situation that I havent encounted before and I am ripping my hair out trying to figure out how to do... I have a form on a webpage that sends data to my PERL script when you hit the submit button - nothing unusual there, but then within my PERL script I need it to post off variables to another webpage and load that page up (basicly simulating a form post within PERL). I've tried various different ways that people have shown me and all of them dont work! It cant be that hard can it?

Do I need to use sockets? or can it just be accomplished with just a simple HTTP header? ... also I want to steer clear of the CGI and LWP modules... just raw code cause its the best!... thanks in advance...

Am I heading in the right direction doing it this way? I don't know...

use IO::Socket; $host="localhost"; $path="/cgi-bin/display_passed_args.pl"; $str="test1=foo&test2=bar"; $sock = IO::Socket::INET->new("$host:80"); $sock->autoflush(); print $sock "POST $path HTTP/1.0\n"; print $sock "Host: $host\n"; print $sock "Content-type: application/x-www-form-urlencoded\n"; print $sock "Content-length: ".length($str)."\n"; print $sock "Connection: close\n\n"; print $sock $str;

Replies are listed 'Best First'.
(jeffa) Re: Simulating Form Posts from within Perl
by jeffa (Bishop) on Aug 02, 2002 at 03:37 UTC
    First, it's Perl - not PERL. :) Second, LWP is GOOOOOD!

    Moving on, consider the following CGI script, which i named simple.cgi:

    #!/usr/bin/perl -Tw use strict; use CGI qw(:standard); print header; if (param('foo')) { print "you sent ", param('foo'); } else { print start_html,start_form,textfield('foo'), submit,end_form,end_html, ; }
    The following LWP script will talk to it:
    use strict; use LWP; use HTTP::Request::Common; my $url = 'http://localhost/cgi-bin/simple.cgi'; my $ua = LWP::UserAgent->new; my $request = POST($url, Content => [foo=>'hello world']); my $response = $ua->request($request); print $response->content, "\n";
    Now, was that so bad? CGI.pm and LWP.pm are your friends. :) Use them! Just to show that i am a nice guy, here is an example that uses IO::Socket and GET to do roughly the same thing (oh, you were forgetting to read the results back, by the way):
    use strict; use IO::Socket qw(:DEFAULT :crlf); $/ = CRLF . CRLF; my $sock = IO::Socket::INET->new( Proto => 'tcp', PeerAddr => 'localhost', PeerPort => 'http(80)', ); print $sock "GET /cgi-bin/simple.cgi?foo=hello%20world",$/; my $header = <$sock>; print $header; my $data; print $data while read($sock,$data,1024) > 0;
    Much uglier in my opinion, and definitely less robust. If you plan to stick with raw sockets, then i suggest you buy and read Network Programming with Perl. Good luck! :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      ok Jeffa, thank you very much for your detailed suggestions, I'll try it out.
Re: Simulating Form Posts from within PERL
by dws (Chancellor) on Aug 02, 2002 at 06:55 UTC
    Compare jeffa's code with the LWP equivalent:
    #!/usr/bin/perl -w use HTTP::Request::Common qw(POST); use LWP::UserAgent; my $url = "http://localhost/cgi-bin/display_passed_args.pl"; my $ua = new LWP::UserAgent(); my $request = POST $url, [ test1 => "foo", test2 => "bar" ]; my $response = $ua->request($request); print $response->as_string();
    By using LWP, you get to focus on the request/response process at a higher level.

Re: Simulating Form Posts from within PERL
by Dog and Pony (Priest) on Aug 02, 2002 at 07:31 UTC
    I really like posting links, so in addition to the above suggestions, might I point you to lwpcook, especially the section about POSTs? Doesn't hurt to have the docs to study as well as live examples. :)

    As pointed out, LWP is your friend - it is one of my most used modules, since it is both powerful and easy to use.


    You have moved into a dark place.
    It is pitch black. You are likely to be eaten by a grue.
Re: Simulating Form Posts from within PERL
by moxliukas (Curate) on Aug 02, 2002 at 10:46 UTC

    In addition to what other monks have suggested (using LWP and reading lwpcook) I would also like to add that you could look at the HTML::Form module (it uses LWP internally, but it sure did simplify the task of submitting forms for me).

    Just my $0.02

Re: Simulating Form Posts from within PERL
by rse (Initiate) on Aug 02, 2002 at 16:44 UTC
    I wouldn't bother using Socket unless you have a real good reason. I've done a bit of Socket development myself. It really forces you to learn what the protocol is *really* doing. Once you are done understanding it, or no-longer care to, just use LWP:
    # Create a user agent object use LWP::UserAgent; $ua = LWP::UserAgent->new; $ua->agent("MyApp/0.1 "); # Create a request my $req = HTTP::Request->new(POST => 'http://www.perl.com/cgi-bin/Bug +Glimpse'); $req->content_type('application/x-www-form-urlencoded'); $req->content('match=www&errors=0'); # Pass request to the user agent and get a response back my $res = $ua->request($req);
    --Good Luck ;)
Re: Simulating Form Posts from within PERL
by sauoq (Abbot) on Aug 03, 2002 at 02:06 UTC
    First, I agree with previous posters that using LWP is probably a good thing.

    That said, it looks like what you have is fine.

    You might want to add:

    print while (<$sock>);
    at the end of it so that you can see what the server returns.

    Update: What you have is fine with my setup. I tested it against the following cgi script:

    #!/usr/bin/perl use CGI; my $q = new CGI; my @keys = $q->param; print "Content-type: text/plain\n\n"; print "$_ ",$q->param($_),"\n" for (@keys);
    The ouput was exactly what you'd expect. The only change I made was to the path of the cgi. (I also added my suggestion above so that I could see the output.)
     
    -sauoq
    "My two cents aren't worth a dime.";