#!/usr/bin/perl # File: lwp-http-post.monitor # Author: Kastus Shchuka, kastus@epocrates.com # Date: Thu Apr 18 19:10:11 PDT 2002 # Description: Perform an HTTP POST preceded by GET to set cookies, following redirections -- using LWP. # Based on: lwp-http.mon by Daniel Hagerty, hag@linnaean.org # #use strict; use LWP::UserAgent; use HTTP::Cookies; use HTTP::Request::Common qw(GET POST); use Getopt::Std; use File::Basename; use URI; ### use vars qw($opt_h $opt_p $opt_t $opt_z $opt_d $opt_r $opt_s $opt_P $opt_v $opt_c $opt_f); ## # Configure this. my $maintainer = 'unixteam@epocrates.com'; ## my $port; my $directory; my $regex; my $proto = "http"; my $timeout = 60; my $formdata; my $version = "0.1"; my $agent = "Yet Another Monitor Bot/$version"; my $u_proto; # We make our own specialization of LWP::UserAgent that performs # redirection in POST requests { package RequestAgent; @ISA = qw(LWP::UserAgent); sub new { my $self = LWP::UserAgent::new(@_); $self->agent("lwp-request/$main::VERSION"); $self; } sub redirect_ok { 1; } } ### sub main { do_usage() if(@_ == 0); $directory = $opt_d if($opt_d); $port = $opt_p if($opt_p); $timeout = $opt_t if($opt_t); $regex = $opt_r if($opt_r); $proto = "https" if ($opt_s); $proto = $opt_P if($opt_P); $formdata = $opt_f if ($opt_f); $directory =~ s/^\///; # Nuke leading slash $u_proto = $proto; $u_proto =~ tr/[a-z]/[A-Z]/; my $ua = RequestAgent->new() || lose("LWP create failure"); $ua->agent($agent); $ua->from($maintainer); $ua->timeout($timeout); my @failed; my %failure; host: foreach my $host (@_) { my $ht_lose = sub { push(@failed, $host); $failure{$host} = join(" ", @_); # This generates a warning. next host; }; if($opt_c) { # Generate new cookies for each host. my $cookies = HTTP::Cookies->new() || &{$ht_lose}("HTTP::Cookies create failure"); $ua->cookie_jar($cookies); } my $uri_str = "$proto://$host/$directory"; my $request = HTTP::Request->new("GET" => $uri_str) || &{$ht_lose}("HTTP::Request create failure"); my $req = GET $uri_str; my $uri = $req->uri(); $uri->port($port) if(defined($port)); my $response = $ua->request($req) || &{$ht_lose}("UserAgent GET request failure"); unless($response->is_success) { &{$ht_lose}("Request failed:", $response->message); } $req = POST $uri_str; my $uri = $req->uri(); $uri->port($port) if(defined($port)); $req->content($formdata); $response = $ua->request($req) || &{$ht_lose}("UserAgent POST request failure"); unless($response->is_success) { &{$ht_lose}("Request failed:", $response->message); } my $strref = $response->content_ref; if(!$opt_z && length($$strref) == 0) { &{$ht_lose}("Empty document"); } if(defined($regex)) { my $winning; map {$winning++ if(/$regex/);} split("\n", $$strref); if($opt_v) { &{$ht_lose}("Failure regex matches:", $winning) if($winning); } elsif(!$winning) { &{$ht_lose}("Regex not found"); } } } if(@failed) { print "$u_proto Failures: " . join(" ", @failed) . "\n"; foreach my $fail (@failed) { print "$fail: $failure{$fail}\n"; } exit(1); } exit; } sub lose { die join(" ", @_); } sub do_usage { my $extended = shift; my $base = basename $0; print STDERR "Usage: $base [options...] hosts ...\n"; if($extended) { print <<'EOF'; -h Help. You're reading it. -d URL URL to test on the remote host. Default is /. -p PORT Port to connect to. Default is proto specific. -P PROTO Protocol to fetch. Default is http. -s Fetch via https. Equivalent to -P https. -t TIMEOUT Timeout for the fetch. Default is 60 seconds. -r REGEX A regular expression that the retrieved content must match. -v Invert the regular expression. Content must NOT match. -z Supress zero-length check. -c Enable Cookies. -f FORMDATA form data in url-encoded format, e.g. login_name=foo&pwd=bar EOF } exit 1; } ### getopts("hszvcp:t:d:r:P:f:") || do_usage(); do_usage($opt_h) if($opt_h); &main(@ARGV); # EOF