【发布时间】:2021-02-13 09:57:22
【问题描述】:
到目前为止我的目标和目标
我正在尝试将 Azuure 存储 Blob 服务 REST API 与 Node.JS 一起使用。到目前为止,我成功地请求了 List Containers 和 Get Blob Services Properties 操作。现在我正在尝试基于来自 MS 的 this documentation 的 Put Blob。
我遇到了 400 和 403 错误并搜索了类似的问题,即使它是 a question on C# 或 on R 而不是 Node.JS,阅读它帮助我了解我可能做错了什么并更改我的代码。在这种情况下,缺少更清晰文档的是签名及其规范化资源和规范化标头。
问题
当我认为我解决了签名问题(在所有响应停止告诉我那是问题之后)并且现在我不再有这些错误时,所发生的只是:我提出请求并冻结了一段时间尽管;一段时间后我收到消息:
events.js:292
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at TLSWrap.onStreamRead (internal/stream_base_commons.js:205:27)
Emitted 'error' event on ClientRequest instance at:
at TLSSocket.socketErrorListener (_http_client.js:426:9)
at TLSSocket.emit (events.js:315:20)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
errno: 'ECONNRESET',
code: 'ECONNRESET',
syscall: 'read'
}
从this question on a similar issue 我了解到这是 TCP 另一端的中断连接。所以它可能不再是签名了,但我不知道它是什么。我需要在Put Blob 之前提出其他类型的请求吗?
我尝试更改签名,还尝试创建要上传的本地 .txt 文件,并尝试从变量上传简单字符串。 我不确定应该从哪里上传数据。
我认为我的主要问题是,对于我遇到的其他错误和问题,我得到了一些信息(最终在大量阅读之后)解决它;但现在我什至没有获得 Status 200。
代码
我创建签名的函数:
/**
* Authorization using HMAC SHA 256.
* @param {String} VERB - Request method to be used (GET, PUT).
* @param {String} strTime - Time of the request, in RFC 1123 Format.
* @param {String} path - Path of the URL, containing the name of the
* container and the query parameters.
*/
create_signature(VERB, strTime, uri, content) {
VERB = VERB.toUpperCase();
// removing first slash
uri = uri.replace("/","");
// separating '/container/blob?q=query&q=query' into 'container/blob' and 'q=query&q=query'
var [path, query] = uri.split("?");
// changing 'q=query&q=query' to 'q:query\nq:query' if '?' is included
query = query ? query.replace(/\=/g,":").replace(/\&/g,"\n") : '';
// without the '?' char the separation is '/container/blob' and ''
const content_type = "text/plain; charset=UTF-8";
const content_length = content.length.toString();
let strToSign = VERB + "\n" + // VERB
"\n" + // Content-Encoding
"\n" + // Content-Language
content_length + "\n" + // Content-Length
"\n" + // Content-MD5
content_type + "\n" + // Content-Type
"\n" + // Date
"\n" + // If-Modified-Since
"\n" + // If-Match
"\n" + // If-None-Match
"\n" + // If-Unmodified-Since
"\n" + // Range
// CanonicalizedHeaders
`x-ms-blob-type:BlockBlob` + "\n" +
`x-ms-date:${strTime}` + "\n" +
`x-ms-version:${this.version}` + "\n" +
// CanonicalizedResource
`/${this.account_name}/${path}`;
console.log(strToSign);
// strToSign = strToSign.toLowerCase();
// strToSign = encodeURIComponent(strToSign);
// generating secret from account key
var secret = CryptoJS.enc.Base64.parse(this.account_key);
// encrypting the signature
var hash = CryptoJS.HmacSHA256(strToSign, secret);
var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);
var auth_sig = `SharedKey ${this.account_name}:` + hashInBase64;
return auth_sig;
}
使用 http 模块发出请求:
// making the request using the http module:
put_blob(container_name, filename) {
const time_UTC_str = new Date().toUTCString();
var path = `/${container_name}/${filename}`;
const obj = "hello world";
const signature = this.create_signature('PUT', time_UTC_str, path, obj);
const req_params = {
method: 'PUT',
hostname: this.hostname,
path: path,
headers: {
'Authorization': signature,
'x-ms-date': time_UTC_str,
'x-ms-version': this.version,
'x-ms-blob-type': 'BlockBlob',
'Content-Length': obj.length.toString(),
'Content-Type': "text/plain; charset=UTF-8"
}
}
let req = http.request(req_params, this.res_handler);
req.end();
}
响应处理函数:
/**
* Callback function that handles and parses the responses,
* including how the search results will be processed.
* @param {object} res - response from request
*/
res_handler = function (res) {
let body = '';
// storing body
res.on('data', (dat) => {
body += dat;
});
// when signaling 'end' flag
res.on('end', () => {
// parsing response
if (!res.complete) {
console.error('The connection was terminated while the message was still being sent');
} else {
// console.log(res);
console.log(`Status: ${res.statusCode} - ${res.statusMessage}`);
}
console.log('Response: ' + body);
});
// handling errors
res.on('error', (err) => {
console.error(`Error ${err.statusCode}: ${err.statusMessage}`);
});
};
PS:我应该尝试其他云服务还是它们都复杂且记录不充分?
【问题讨论】:
标签: node.js azure http azure-blob-storage