如何仅使用标准Perl库发出HTTP POST请求?

时间:2009-09-05 18:48:18

标签: perl

假设系统仅包含基本的Perl安装而没有任何额外的CPAN模块(因此LWP NOT )。我的一些目标环境空间有限,我根本无法增加我的足迹(否则我会使用LWP)。

从这样的系统发出HTTP POST请求,然后检索响应的最便携和可靠的方法是什么?

5 个答案:

答案 0 :(得分:16)

HTTP::Lite是纯Perl,因此您可以将其与现有代码捆绑在一起。

答案 1 :(得分:12)

考虑一下。 HTTP POST并非易事。您需要将数据组合成MIME blob,正确编码,然后打开Socket连接,发送数据,然后从套接字读取任何响应头以确保它有效。

你将做很多工作来复制LWP已经做的事情,然后你将完成所有工作并把它放在你没有LWP的环境中。

此时,您会问自己,“哎呀,如果我可以将自己的 Perl代码放在这个环境中,为什么我不能把LWP放在那里?”

永远不要害怕,因为我在这里为你节省了三个月无用的工作。

How to install Perl modules locally

如果你不能那样做,那么

How to use PAR to package and distribute dependencies

祝你好运,不要重复代码。

答案 2 :(得分:3)

查看是否有其他可用的程序可以调用来执行帖子。例如curl,wget,lynx或Java。

答案 3 :(得分:2)

我只是这样做HTTP Post而不使用任何库,

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;
}

我将它与真正的旧服务器(第一代Apache httpd)一起使用。它不支持HTTP / 1.1,分块编码等,但你明白了。

答案 4 :(得分:0)

如果您只想发布纯文本,HTTP POST 真的很简单,这对于大多数应用程序来说就足够了。

我使用此代码,它只需要 IO::Socket(在我的 NAS 上使用 perl 5.8.8 运行)将传感器数据(通过 UDP 在我的 LAN 上获取,也通过另一个 IO::Socket)发布到 influxdb 服务器上互联网:

my $REMOTE = new IO::Socket::INET (PeerAddr => 'yourhostname.com', PeerPort => '8086',
                                   Proto => 'tcp', Timeout => '1', Blocking => '0')                 
   or die "can't connect - connection busy?";                                                       
$REMOTE->autoflush(1);                                                                              
                                                                                                    
my $data = "POOL ph=$ph,orp=$orp";                                                                
my $len = length($data);                                                                          
print $REMOTE "POST /write?db=esp-sensors HTTP/1.1\n",                              
              "Host: yourhostname.com\n",                                                    
              "Connection: close\n",                                                
              "Content-Type: application/x-www-form-urlencoded\n",                  
              "Content-Length: $len\n\n",                                           
              "$data\n";                                                            
close($REMOTE);      

当然,我不检查结果。但我认为这是可能的。由于无论如何我对任何失败都无能为力,我不在乎它是否失败,总有一天我会看到图表中缺少数据并检查发生了什么。