19f11ffb7Safresh1package Util; 2898184e3Ssthen 3898184e3Ssthenuse strict; 4898184e3Ssthenuse warnings; 5898184e3Ssthen 6898184e3Ssthenuse IO::File qw(SEEK_SET SEEK_END); 7898184e3Ssthenuse IO::Dir; 8898184e3Ssthen 9898184e3SsthenBEGIN { 10898184e3Ssthen our @EXPORT_OK = qw( 11898184e3Ssthen rewind 12898184e3Ssthen tmpfile 13898184e3Ssthen dir_list 14898184e3Ssthen slurp 15898184e3Ssthen parse_case 16898184e3Ssthen hashify 17898184e3Ssthen sort_headers 18898184e3Ssthen connect_args 19898184e3Ssthen clear_socket_source 20898184e3Ssthen set_socket_source 21898184e3Ssthen monkey_patch 22898184e3Ssthen $CRLF 23898184e3Ssthen $LF 24898184e3Ssthen ); 25898184e3Ssthen 26898184e3Ssthen require Exporter; 27898184e3Ssthen *import = \&Exporter::import; 28898184e3Ssthen} 29898184e3Ssthen 30898184e3Ssthenour $CRLF = "\x0D\x0A"; 31898184e3Ssthenour $LF = "\x0A"; 32898184e3Ssthen 33898184e3Ssthensub rewind(*) { 34898184e3Ssthen seek($_[0], 0, SEEK_SET) 35898184e3Ssthen || die(qq/Couldn't rewind file handle: '$!'/); 36898184e3Ssthen} 37898184e3Ssthen 38898184e3Ssthensub tmpfile { 39898184e3Ssthen my $fh = IO::File->new_tmpfile 40898184e3Ssthen || die(qq/Couldn't create a new temporary file: '$!'/); 41898184e3Ssthen 42898184e3Ssthen binmode($fh) 43898184e3Ssthen || die(qq/Couldn't binmode temporary file handle: '$!'/); 44898184e3Ssthen 45898184e3Ssthen if (@_) { 46898184e3Ssthen print({$fh} @_) 47898184e3Ssthen || die(qq/Couldn't write to temporary file handle: '$!'/); 48898184e3Ssthen 49898184e3Ssthen seek($fh, 0, SEEK_SET) 50898184e3Ssthen || die(qq/Couldn't rewind temporary file handle: '$!'/); 51898184e3Ssthen } 52898184e3Ssthen 53898184e3Ssthen return $fh; 54898184e3Ssthen} 55898184e3Ssthen 56898184e3Ssthensub dir_list { 57898184e3Ssthen my ($dir, $filter) = @_; 58898184e3Ssthen $filter ||= qr/./; 59898184e3Ssthen my $d = IO::Dir->new($dir) 60898184e3Ssthen or return; 61898184e3Ssthen return map { "$dir/$_" } sort grep { /$filter/ } grep { /^[^.]/ } $d->read; 62898184e3Ssthen} 63898184e3Ssthen 64898184e3Ssthensub slurp (*) { 65898184e3Ssthen my ($fh) = @_; 66898184e3Ssthen 67898184e3Ssthen seek($fh, 0, SEEK_END) 68898184e3Ssthen || die(qq/Couldn't navigate to EOF on file handle: '$!'/); 69898184e3Ssthen 70898184e3Ssthen my $exp = tell($fh); 71898184e3Ssthen 72898184e3Ssthen rewind($fh); 73898184e3Ssthen 74898184e3Ssthen binmode($fh) 75898184e3Ssthen || die(qq/Couldn't binmode file handle: '$!'/); 76898184e3Ssthen 77898184e3Ssthen my $buf = do { local $/; <$fh> }; 78898184e3Ssthen my $got = length $buf; 79898184e3Ssthen 80898184e3Ssthen ($exp == $got) 81898184e3Ssthen || die(qq[I/O read mismatch (expexted: $exp got: $got)]); 82898184e3Ssthen 83898184e3Ssthen return $buf; 84898184e3Ssthen} 85898184e3Ssthen 86898184e3Ssthensub parse_case { 87898184e3Ssthen my ($case) = @_; 88898184e3Ssthen my %args; 89898184e3Ssthen my $key = ''; 90*eac174f2Safresh1 my %seen; 91898184e3Ssthen for my $line ( split "\n", $case ) { 92898184e3Ssthen chomp $line; 93898184e3Ssthen if ( substr($line,0,1) eq q{ } ) { 94898184e3Ssthen $line =~ s/^\s+//; 95898184e3Ssthen push @{$args{$key}}, $line; 96898184e3Ssthen } 97898184e3Ssthen else { 98898184e3Ssthen $key = $line; 99*eac174f2Safresh1 $seen{$key}++; 100898184e3Ssthen } 101898184e3Ssthen } 102*eac174f2Safresh1 for my $k (keys %seen) { 103*eac174f2Safresh1 $args{$k}=undef unless exists $args{$k}; 104*eac174f2Safresh1 } 105898184e3Ssthen return \%args; 106898184e3Ssthen} 107898184e3Ssthen 108898184e3Ssthensub hashify { 109898184e3Ssthen my ($lines) = @_; 110898184e3Ssthen return unless $lines; 111898184e3Ssthen my %hash; 112898184e3Ssthen for my $line ( @$lines ) { 113898184e3Ssthen my ($k,$v) = ($line =~ m{^([^:]+): (.*)$}g); 114898184e3Ssthen $hash{$k} = [ $hash{$k} ] if exists $hash{$k} && ref $hash{$k} ne 'ARRAY'; 115898184e3Ssthen if ( ref($hash{$k}) eq 'ARRAY' ) { 116898184e3Ssthen push @{$hash{$k}}, $v; 117898184e3Ssthen } 118898184e3Ssthen else { 119898184e3Ssthen $hash{$k} = $v; 120898184e3Ssthen } 121898184e3Ssthen } 122898184e3Ssthen return %hash; 123898184e3Ssthen} 124898184e3Ssthen 125898184e3Ssthensub sort_headers { 126898184e3Ssthen my ($text) = shift; 127898184e3Ssthen my @lines = split /$CRLF/, $text; 128898184e3Ssthen my $request = shift(@lines) || ''; 129898184e3Ssthen my @headers; 130898184e3Ssthen while (my $line = shift @lines) { 131898184e3Ssthen last unless length $line; 132898184e3Ssthen push @headers, $line; 133898184e3Ssthen } 134898184e3Ssthen @headers = sort @headers; 135898184e3Ssthen return join($CRLF, $request, @headers, '', @lines); 136898184e3Ssthen} 137898184e3Ssthen 138898184e3Ssthen{ 139898184e3Ssthen my (@req_fh, @res_fh, $monkey_host, $monkey_port); 140898184e3Ssthen 141898184e3Ssthen sub clear_socket_source { 142898184e3Ssthen @req_fh = (); 143898184e3Ssthen @res_fh = (); 144898184e3Ssthen } 145898184e3Ssthen 146898184e3Ssthen sub set_socket_source { 147898184e3Ssthen my ($req_fh, $res_fh) = @_; 148898184e3Ssthen push @req_fh, $req_fh; 149898184e3Ssthen push @res_fh, $res_fh; 150898184e3Ssthen } 151898184e3Ssthen 152898184e3Ssthen sub connect_args { return ($monkey_host, $monkey_port) } 153898184e3Ssthen 154898184e3Ssthen sub monkey_patch { 155898184e3Ssthen no warnings qw/redefine once/; 156898184e3Ssthen *HTTP::Tiny::Handle::can_read = sub {1}; 157898184e3Ssthen *HTTP::Tiny::Handle::can_write = sub {1}; 158898184e3Ssthen *HTTP::Tiny::Handle::connect = sub { 1599f11ffb7Safresh1 my ($self, $scheme, $host, $port, $peer) = @_; 160898184e3Ssthen $self->{host} = $monkey_host = $host; 161898184e3Ssthen $self->{port} = $monkey_port = $port; 1629f11ffb7Safresh1 $self->{peer} = $peer; 1636fb12b70Safresh1 $self->{scheme} = $scheme; 164898184e3Ssthen $self->{fh} = shift @req_fh; 165b8851fccSafresh1 $self->{pid} = $$; 166b8851fccSafresh1 $self->{tid} = HTTP::Tiny::Handle::_get_tid(); 167898184e3Ssthen return $self; 168898184e3Ssthen }; 169898184e3Ssthen my $original_write_request = \&HTTP::Tiny::Handle::write_request; 170898184e3Ssthen *HTTP::Tiny::Handle::write_request = sub { 171898184e3Ssthen my ($self, $request) = @_; 172898184e3Ssthen $original_write_request->($self, $request); 173898184e3Ssthen $self->{fh} = shift @res_fh; 174898184e3Ssthen }; 175898184e3Ssthen *HTTP::Tiny::Handle::close = sub { 1 }; # don't close our temps 176*eac174f2Safresh1 *HTTP::Tiny::Handle::connected = sub { 1 }; 177898184e3Ssthen 1786fb12b70Safresh1 # don't try to proxy in mock-mode 179b8851fccSafresh1 delete $ENV{$_} for map { $_, uc($_) } qw/http_proxy https_proxy all_proxy/; 180898184e3Ssthen } 181898184e3Ssthen} 182898184e3Ssthen 183898184e3Ssthen1; 184898184e3Ssthen 185898184e3Ssthen 186898184e3Ssthen# vim: et ts=4 sts=4 sw=4: 187