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>