Home > Blockchain >  Azure REST API PUT Header in Node.js for Copying Blob
Azure REST API PUT Header in Node.js for Copying Blob

Time:10-25

Running the below GET request node.js works:

const CryptoJS = require("crypto-js");
const account = 'account'
const containerName = 'container'
const blobName = 'picture.jpeg'
const blobUrl = `https://${account}.blob.core.windows.net/${containerName}/${blobName}`

const key = 'accesskey'
const strTime = (new Date()).toUTCString();
const strToSign = `GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:${strTime}\nx-ms-version:2020-10-02\n/${account}/\ncomp:list`;

const secret = CryptoJS.enc.Base64.parse(key);
const hash = CryptoJS.HmacSHA256(strToSign, secret);
const hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
const auth = `SharedKey ${account}:` hashInBase64; 

let getConfig = {
    headers: {
        'Authorization': auth,
        'x-ms-date': strTime,
        'x-ms-version': "2020-10-02",
    }
}

   
export default async (req, res) => {
    if (req.method === 'POST') {

        fetch(`https://${account}.blob.core.windows.net/?comp=list`, getConfig)
        .then( results => {
            if(results.status==200) {console.log('api works')} else {console.log(results)}},
            res.end()
        )
    } 
}

I then want to copy a blob with access tier "Archive". Running the same code with the below changes for a PUT request doesn't work:

const blobUrl = https://${account}.blob.core.windows.net/${containerName}/${blobName}

const strToSign = PUT\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:${strTime}\nx-ms-version:2020-10-02\n/${account}/\n${containerName}/\n${blobName};

const putConfig = {
    method: 'PUT', 
    headers: {
        'Authorization': auth,
        'x-ms-date': strTime,
        'x-ms-version': "2020-10-02",
        'x-ms-copy-source': blobUrl,
        'x-ms-requires-sync':'true',
    }
}
    

fetch(https://${account}.blob.core.windows.net/${containerName}/${blobName}, putConfig)

Can anyone tell me what I need to change to run the PUT request successfully?

CodePudding user response:

You will need to add x-ms-copy-source and x-ms-requires-sync request headers in your 2nd strToSign.

Essentially you will need to include all headers starting with x-ms in your canonicalized headers string.

You will also need to ensure that these headers are sorted alphabetically.

So your strToSign would be something like:

const strToSign = PUT\n\n\n\n\n\n\n\n\n\n\n\nx-ms-copy-source:${blobUrl}\nx-ms-date:${strTime}\nx-ms-requires-sync:true\nx-ms-version:2020-10-02\n/${account}/\n${containerName}/\n${blobName}

Where blobUrl is the URL for the source blob that you want to copy.

Please see this link for more details: https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key#constructing-the-canonicalized-headers-string.

On a side note, have you looked at Azure Blob SDK for JavaScript?

CodePudding user response:

You need to provide Required attributes in the headers of the putConfig.

So, I see, two required attributes missing at this moment. x-ms-lease-id:<ID> and Content-Length: 0 For a page blob or an append blob, the Content-Length value of this header must be set to zero, as Put Blob is used only to initialize the blob.

const putConfig = {
    method: 'PUT', 
    headers: {
        'Authorization': auth,
        'x-ms-date': strTime,
        'x-ms-version': "2020-10-02",
        'x-ms-copy-source': blobUrl,
        'x-ms-requires-sync':'true',
        'x-ms-lease-id': <ID>,
        'Content-Length': 0,
    }
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

In the getConfig, You have used x-ms-version above of 2012-02-12. So In version 2012-02-12 and newer, the x-ms-lease-id:<ID> value must specify an active, infinite lease for a leased blob. A finite-duration lease ID fails with 412 (Precondition Failed).

Please see this link for more details: https://docs.microsoft.com/en-us/rest/api/storageservices/copy-blob

So, You need to update the getConfig like this:-

let getConfig = {
    headers: {
        'Authorization': auth,
        'x-ms-date': strTime,
        'x-ms-version': "2020-10-02",
        'x-ms-lease-id': <ID>,
    }
}
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related