Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I issue an HTTP POST request using only standard Perl libraries?

Tags:

perl

Assume a system that contains only the basic Perl installation without any extra CPAN modules (LWP is hence NOT installed). Some of my target environments have limited space and I cannot increase my footprint at all (otherwise I would use LWP).

What is the most portable and reliable way to issue a HTTP POST request from such a system, and then retrieve the response?

like image 919
knorv Avatar asked Sep 05 '09 18:09

knorv


4 Answers

HTTP::Lite is pure-Perl, so you can just bundle it along with your existing code.

like image 184
Charles Avatar answered Oct 12 '22 04:10

Charles


Consider this. HTTP POSTs are not trivial. You need to assemble the data into a MIME blob, encode it properly, then open a Socket connection, send the data, then read any response headers from the socket to make sure it worked.

You'll be doing a lot of work to duplicate what LWP already does, and then you'll take all that work and put it in your environment that doesn't have LWP.

At that point, you will ask yourself, "gee, if I can put my own Perl code on this environment, why can't I just put LWP there?"

Never fear, for I am here to save you three months of useless work.

How to install Perl modules locally

If you can't do that, then

How to use PAR to package and distribute dependencies

Good luck, and don't duplicate code.

like image 22
friedo Avatar answered Oct 12 '22 04:10

friedo


I just do HTTP Post like this without using any library,

sub post {
    local($host,$port,$request,$data) = @_;
    ($fqdn, $aliases, $type, $len, $thataddr) = gethostbyname($host);
    $that = pack($sockaddr, &AF_INET, $port, $thataddr);
    socket(FS, &AF_INET, &SOCK_STREAM, $proto) || return undef;
    bind(FS, $thissock) || return undef;
    local($/);
    unless (eval q!
        $SIG{'ALRM'} = "timeout";
        alarm($timeout);
        connect(FS, $that) || return undef;
        select(FS); $| = 1; select(STDOUT);

        print FS "POST $request HTTP/1.0\r\n$referer";
        print FS "$useragent";
        print FS "Host: $host:$port\r\n$mimeaccept";
        print FS "$cnt_type";
        $len = length($data);
        print FS "Content-length: $len\r\n\r\n$data\r\n";
        undef($page);
        $/ = "\n";
        $_ = <FS>;
        if (m:HTTP/1.0\s+\d+\s+:) { #HTTP/1.0
          while(<FS>) {
            last if /^[\r\n]+$/; # end of header
          }
          undef($/);
          $page = <FS>;
        }
        else {    # old style server reply
          undef($/);
          $page = $_;
          $_ = <FS>;            
          $page .= $_;
        }
        $SIG{'ALRM'} = "IGNORE";
        !) {
            return undef;
        }
    close(FS);
    $page;
}

I use this with a real old server (first generation Apache httpd). It doesn't support HTTP/1.1, chunked encoding etc but you get the idea.

like image 35
ZZ Coder Avatar answered Oct 12 '22 05:10

ZZ Coder


See if there are any other programs available that you could call to perform the post. curl, wget, lynx, or Java for example.

like image 32
Kenster Avatar answered Oct 12 '22 04:10

Kenster