Azure REST API“Put Block”错误596?

时间:2016-03-21 12:20:55

标签: perl azure azure-storage

我在Azure Blob服务错误代码列表https://msdn.microsoft.com/en-us/library/dd179439.aspx中看不到与错误596相关的任何信息。

我正在尝试将一些块上传到Azure服务,并从API获取代码596和描述'Broken pipe'的回复。

有没有人遇到过这个?

(N.B。是的,我知道下面的代码尚未完成,因为代码原样没有上传最终的块)

#!/usr/bin/perl

use 5.014;
use strict;
use warnings;
use autodie;

use Data::Dumper;
use Digest::MD5 qw(md5_base64);
use Crypt::PRNG::Fortuna qw(random_bytes_b64u random_bytes);
use Digest::SHA qw(hmac_sha256_base64);
use Getopt::Long;
use Sys::Syslog qw( :DEFAULT setlogsock);
use File::stat;
use AnyEvent;
use AnyEvent::HTTP;
use Time::Piece;
use Encode qw(decode encode);
use MIME::Base64 qw(encode_base64 decode_base64 encode_base64url);
use FileHandle;
use Fcntl ':flock', 'SEEK_SET';

delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
use sigtrap 'handler' => \&term_handler, 'normal-signals';

####### PARAMS

my $script="upload.pl";
my $maxSingleUpload=1048576; # Maximum size of a single attempt upload (in bytes);
my $multiChunkSize=4194304; # Maximum size of a single block (in bytes)
my $multiLimit=6; # Maximum number of parallel HTTP requests

####### AZURE
my $azureKey="<REMOVED>";
my $azureKeyBin=decode_base64($azureKey);

####### ARGS

my ($vault,$container,$localfile,$remotefile);
my $debug=0;

GetOptions(
        "vault|v=s" => \$vault,
        "container|c=s" => \$container,
    "localfile|l=s" => \$localfile,
    "remotefile|r=s" => \$remotefile,
        "debug|d+" => \$debug
        );

if (!defined $vault || !defined $container || !defined $localfile || !defined $remotefile) {
    say "USAGE: -v <vault> -c <container> -l <localfile> -r <remotefile> [-d (debug)]";
    exit 1;
}

if (!-e $localfile) {
    say "Local file does not exist !";
    exit 1;
}

####### Vars

my ($wholeChunks,$chunkRemainder,$runID,$condvar,@offsets,@blocklist);
my $activeCount=0;

my $putBlockURL="https://${vault}.blob.core.windows.net/${container}/${remotefile}?comp=block&blockid=";

####### FUNCTIONS

# Quotient remainder calculator

sub qrem {
    use integer;
    my( $dividend, $divisor ) = @_;
    my $quotient = $dividend / $divisor;
    my $remainder = $dividend % $divisor;
    my @result = ( $quotient, $remainder );
    return @result;
}

# Do pad
sub doPad {
        my ($raw) = @_;
        while (length($raw) % 4) {
                $raw .= '=';
        }
        return $raw;
}

# Random

sub getRandom {
    my ($len) = @_;
    #return doPad(random_bytes_b64u($len));
    return doPad(encode_base64(random_bytes($len)));
}

# Term handler

sub term_handler {
        doLog("err","term_handler: Program terminated early due to user input");
        exit 2;
}

# Log sub
sub doLog {
        my ($priority,$msg) = @_;
        return 0 unless ($priority =~ /info|err|debug/);
        setlogsock('unix');
        openlog($script, 'pid,cons', 'user');
        syslog($priority, $msg);
        closelog();
        return 1;
}

# Get file size
sub fileSz {
    my($file) = @_;
    my $stat = stat($file);
    return $stat->size;
}

# Get data
sub readData {
    my ($file,$length,$offset)=@_;
    my $fh = FileHandle->new;
    my ($data);
    if ($debug) { say "Reading ${file} offset ${offset} for length ${length}";}
    #open ($fh,"<",$file);
    $fh->open("< $file");
    binmode($fh);
    seek($fh,$offset,SEEK_SET);
    read($fh,$data,$length);
    if ($debug) { say "readData read ".byteSize($data);}
    #close($fh);
    $fh->close;
    return $data;
}

# Calc MD5 
sub calcMD5 {
    my ($data)=@_;
    my $hash = md5_base64($data);
    return doPad($hash);
}

# Populate offsets
sub populateOffsets {
    my ($count,$offsetSize)=@_;
    if (!defined $count || !defined $offsetSize) {exit 1;}
    my $offset=0;
    my @offsets;
    for my $i (1..$count) {
        push @offsets,$offset;
        $offset = $offset + $offsetSize;
    }
    return @offsets;
}

# Calc auth string
sub azureAuth {
    my($t,$signstring)=@_;
    if (!defined $signstring) { exit 1;}
    if ($debug) {say "String to sign:${signstring}";}
    my $auth;
    $auth=doPad(hmac_sha256_base64($signstring,$azureKeyBin));
    if ($debug) { say "Sig:${auth}";}
    return $auth;
}

# Byte size

sub byteSize {
    use bytes;
    my ($inval)=@_;
    return length($inval);
}

# Process

sub doProcess {
    return if $activeCount >= $multiLimit;

    my $offset = shift @offsets;
    return if !defined $offset;

    $activeCount++;

    if ($debug) { say "Active:${activeCount}, Offset:${offset}";}
    $condvar->begin;

    my $t = localtime;
    my $tNow = $t->strftime();
    my $blockid = getRandom(8);
    my $subRunID=getRandom(5);
    my $contentLength=$multiChunkSize-1;
    my $content = readData($localfile,$contentLength,$offset);
    my $hash = calcMD5($content);
    if ($debug) { say "Block ID:${blockid}, Hash: ${hash}";}

    my $url = $putBlockURL.$blockid;
        my $canocResource="/${vault}/${container}/${remotefile}\nblockid:${blockid}\ncomp:block";
    my $hdrs="x-ms-client-request-id:${runID}\nx-ms-date:${tNow}\nx-ms-version:2009-09-19";
    my $byteLength=byteSize(${content});
    my $canocHeaders=encode('UTF-8',"PUT\n\n\n${byteLength}\n${hash}\n\n\n\n\n\n\n\n${hdrs}\n${canocResource}",Encode::FB_CROAK);
    my $authData=azureAuth($t,$canocHeaders);
    if ($debug) {say "Length:${byteLength}";say "Sig: ${authData}"; say "URL:${url}";}

    my $azureArr =  {
    "Authorization"=>"SharedKey ${vault}:${authData}",
    "Content-Length"=>${byteLength},
    "Content-MD5"=>${hash},
        "x-ms-version"=>"2009-09-19",
        "x-ms-date"=>${tNow},
        "x-ms-client-request-id"=>"${runID}"
    };

    ####### ERROR OCCURS HERE ....
    http_request "PUT" => $url,
        persistent=>0,
        headers=>$azureArr,
        body=>$content,
        sub {
            my ($body, $hdr) = @_;
            say Dumper($hdr);
            #say "received, Size: ", length $body;
            #say $body;
            $activeCount--;
            $condvar->end;
            doProcess(); 
        };
    return 1;
}



####### MAIN

$runID=getRandom(5);

doLog("info","${runID} Starting upload for ${localfile} (${remotefile})");

if (fileSz($localfile)<$maxSingleUpload) {
    if ($debug) {say "Using single upload method";}
} else {
    if ($debug) {say "Using multi-upload method";}
    # Calculate chunk quantity
    my @chunks = qrem(fileSz($localfile),$multiChunkSize);
    $wholeChunks=$chunks[0];
    $chunkRemainder=$chunks[1];
    if ($debug) {say "Whole chunks (${multiChunkSize}):${wholeChunks}, Remainder:${chunkRemainder}";}
    # Init
    @offsets=populateOffsets(${wholeChunks},${multiChunkSize});
    say Dumper(@offsets);
    $condvar = AnyEvent->condvar;
    # DO IT 
    for (1..$multiLimit) {
        doProcess();
    }
    $condvar->recv;

}

doLog("info","${runID} Upload complete");

exit 0;

1 个答案:

答案 0 :(得分:3)

错误596是AnyEvent :: HTTP返回的客户端错误。您需要在本地调查以了解您遇到此错误的原因。

有关详细信息,请参阅此页面: https://metacpan.org/pod/AnyEvent::HTTP

  

596 - TLS协商,请求发送和报头处理期间的错误。