diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..4a5b9ce0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,29 @@ +module.exports = { + "env": { + "node": true, + "mocha": true + }, + "extends": "standard", + "parserOptions": { + "ecmaVersion": 6 + }, + "rules": { + "indent": [ + "error", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ], + "eqeqeq": [0] + } +}; diff --git a/.gitignore b/.gitignore index 369eea93..73b9a049 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ lib-cov *.out *.pid *.gz +test-env.sh pids logs @@ -18,3 +19,7 @@ results node_modules npm-debug.log test/config.js +package-lock.json + +coverage/ +.nyc_output/ diff --git a/.npmignore b/.npmignore index 3867aec4..ab8c923e 100644 --- a/.npmignore +++ b/.npmignore @@ -1,7 +1,12 @@ test/ test-env.sh .travis.yml +.eslintrc.js coverage.html +gopher.png lib-cov/ Makefile docs/ +examples/ +coverage/ +.nyc_output/ diff --git a/.travis.yml b/.travis.yml index 9aec1f50..dfc092fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,10 @@ language: node_js node_js: -- '4' -- '6' -- '8' + - "6" + - "8" + - "9" + - "10" + - "11" before_script: - export is_travis=true deploy: diff --git a/CHANGELOG.md b/CHANGELOG.md index bbb8a1d4..db2d3950 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,65 @@ ## CHANGE LOG +## v7.2.2 +- 一些log输出问题,travis增加eslint 检查 + +## v7.2.1 +- 修复rtc获取回复存在的问题 + +## v7.2.0 +- 修复node的stream读取的chunk大小比较随意的问题 + +## v7.1.9 +- 修复新版node下resume up方式文件内容被缓存而导致的上传失败 + +## v7.1.8 +- 修复 index.d.ts 文件中zone的设置 + +## v7.1.7 +- 修复form上传在升级mime库后的错误 + +## v7.1.6 +- 修复rs和rsf的https默认域名 +- 升级修复mime库的安全风险 + +## v7.1.5 +- 增加连麦功能 + +## v7.1.3 +- 增加新加坡机房 + +## v7.1.2 +- 增加自定义资源访问响应头部的功能 +- 改进时间戳签名方法,支持复杂urlencode + +### v7.1.1 +- 修复 index.d.ts 中的函数声明错误 + +### v7.1.0 +- 修复时间戳防盗链中存在特殊字符引发的签名错误 +- 修复分片上传的时候最后一块小于2056字节引发的错误 + +### v7.0.9 +- 增加Qiniu方式的管理凭证生成方法以支持新的产品鉴权 + +### v7.0.8 +- 修复分片上传小文件的时候文件读取end的事件bug + +### v7.0.7 +- 给form upload添加默认的crc32校验以避免网络层面的字节反转导致上传内容不正确 +- 修复resume upload在上传小文件的时候出现的上传失败情况 + +### v7.0.6 +- 修复时间戳防盗链算法中对文件名的urlencode不兼容问题 +- 发布index.d.ts文件 + +### v7.0.5 +- 修复zone获取失败时callbackFunc不存在的问题 +- 增加分片上传的时候的progressCallback + +### v7.0.4 +- 增加http&https代理功能 + ### v7.0.2 - 修复cdn刷新文件和目录中方法引用错误 diff --git a/Makefile b/Makefile index 5e707ad3..854e48b0 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,11 @@ -TESTS = test/*.test.js -TIMEOUT = 25000 -REPORTER = spec -MOCHA_OPTS = test: - @NODE_ENV=test ./node_modules/.bin/mocha \ - --require should \ - --reporter $(REPORTER) \ - --timeout $(TIMEOUT) \ - $(MOCHA_OPTS) \ - $(TESTS) + @npm test -test-cov: - @rm -f coverage.html - @$(MAKE) test MOCHA_OPTS='--require blanket' REPORTER=html-cov > coverage.html - #@$(MAKE) test MOCHA_OPTS='--require blanket' REPORTER=travis-cov - @ls -lh coverage.html +test-cov: clean + @npm run cover + @npm run report clean: - rm -rf ./lib-cov coverage.html + rm -rf ./coverage ./.nyc_output -.PHONY: test-cov lib-cov test +.PHONY: test-cov test diff --git a/README.md b/README.md index 4873891b..5dd92d6f 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# Qiniu Resource Storage SDK for Node.js +# Qiniu Cloud SDK for Node.js [![@qiniu on weibo](http://img.shields.io/badge/weibo-%40qiniutek-blue.svg)](http://weibo.com/qiniutek) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE.md) -[![Build Status](https://travis-ci.org/qiniu/nodejs-sdk.v6.png?branch=master)](https://travis-ci.org/qiniu/nodejs-sdk.v6) -[![Code Climate](https://codeclimate.com/github/qiniu/nodejs-sdk.png)](https://codeclimate.com/github/qiniu/nodejs-sdk) +[![Build Status](https://api.travis-ci.org/qiniu/nodejs-sdk.svg?branch=master)](https://travis-ci.org/qiniu/nodejs-sdk) +[![Code Climate](https://codeclimate.com/github/qiniu/nodejs-sdk.svg)](https://codeclimate.com/github/qiniu/nodejs-sdk) [![Latest Stable Version](https://img.shields.io/npm/v/qiniu.svg)](https://www.npmjs.com/package/qiniu) ## 下载 @@ -18,7 +18,7 @@ $ npm install qiniu ### 从 release 版本下载 -下载地址:https://github.com/qiniu/nodejs-sdk/releases +下载地址:[https://github.com/qiniu/nodejs-sdk/releases](https://github.com/qiniu/nodejs-sdk/releases) 这里可以下载到旧版本的SDK,release 版本有版本号,有 [CHANGELOG](https://github.com/qiniu/nodejs-sdk/blob/master/CHANGELOG.md),使用规格也会比较稳定。 @@ -28,7 +28,14 @@ $ npm install qiniu ## 使用 -参考文档:[七牛云存储 Node.js SDK 使用指南](http://developer.qiniu.com/kodo/sdk/nodejs) +参考文档:[七牛云存储 Node.js SDK 使用指南](http://developer.qiniu.com/kodo/sdk/nodejs) + +## 测试 +``` +$ cd ./test/ +$ source test-env.sh +$ mocha --grep 'bucketinfo' +``` ## 贡献代码 diff --git a/docs/nodejs-sdk-v7.md b/docs/nodejs-sdk-v7.md index 71e96043..b7772e99 100644 --- a/docs/nodejs-sdk-v7.md +++ b/docs/nodejs-sdk-v7.md @@ -499,6 +499,30 @@ bucketManager.changeMime(bucket, key, newMime, function(err, respBody, respInfo) }); ``` + +## 修改文件Headers + +``` +var bucket = 'if-pbl'; +var key = 'qiniu.mp4'; +var headers = { + 'Content-Type': 'application/octet-stream', + 'Last-Modified': 'Web, 21 Oct 2015 07:00:00 GMT', + 'x-custom-header-xx': 'value', +}; + +bucketManager.changeHeaders(bucket, key, headers, function(err, respBody, respInfo) { + if (err) { + console.log(err); + //throw err; + } else { + //200 is success + console.log(respInfo.statusCode); + console.log(respBody); + } +}); +``` + ## 修改文件存储类型 diff --git a/examples/atlab_check_qiniu_auth.js b/examples/atlab_check_qiniu_auth.js new file mode 100644 index 00000000..3c87528b --- /dev/null +++ b/examples/atlab_check_qiniu_auth.js @@ -0,0 +1,24 @@ +const qiniu = require('../index.js'); +const proc = require('process'); + +var accessKey = proc.env.QINIU_ACCESS_KEY; +var secretKey = proc.env.QINIU_SECRET_KEY; + +var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); +var reqURL = 'http://serve.atlab.ai/v1/eval/facex-detect'; +var contentType = 'application/json'; +var reqBody = '{"data":{"uri":"https://ors35x6a7.qnssl.com/atshow-face-detection-20170703/1.png"}}'; +var accessToken = qiniu.util.generateAccessTokenV2(mac, reqURL, 'POST', contentType, reqBody); +var headers = { + Authorization: accessToken, + 'Content-Type': contentType +}; + +qiniu.rpc.post(reqURL, reqBody, headers, function (err, body, info) { + if (err) { + console.error(err); + return; + } + console.log(info); + console.log(body); +}); diff --git a/examples/bucket_image_unimage.js b/examples/bucket_image_unimage.js index 6295a441..518a70b2 100644 --- a/examples/bucket_image_unimage.js +++ b/examples/bucket_image_unimage.js @@ -1,30 +1,29 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = "if-pbl"; -var srcSiteUrl = "http://www.baidu.com/"; +var bucket = 'if-pbl'; +var srcSiteUrl = 'http://www.baidu.com/'; var srcHost = null; -bucketManager.image(bucket, srcSiteUrl, srcHost, function(err, respBody, - respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - console.log(respInfo.statusCode); - - //unimage - bucketManager.unimage(bucket, function(err1, respBody1, respInfo1) { - if (err1) { - throw err; - } - console.log(respInfo1.statusCode); - }); - } +bucketManager.image(bucket, srcSiteUrl, srcHost, function (err, respBody, + respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + console.log(respInfo.statusCode); + // unimage + bucketManager.unimage(bucket, function (err1, respBody1, respInfo1) { + if (err1) { + throw err; + } + console.log(respInfo1.statusCode); + }); + } }); diff --git a/examples/cdn_create_timestamp_antileech_url.js b/examples/cdn_create_timestamp_antileech_url.js index 15e936bb..f3f32fc3 100644 --- a/examples/cdn_create_timestamp_antileech_url.js +++ b/examples/cdn_create_timestamp_antileech_url.js @@ -1,16 +1,17 @@ -const qiniu = require("qiniu"); +const qiniu = require('qiniu'); + +var domain = 'http://sq.qiniuts.com'; +var fileName = '1491535764000.png'; +// 加密密钥 +var encryptKey = '**'; + +var query = 'imageView2/2/w/480/format/jpg'; -var domain = 'http://sg.xiaohongshu.com'; -var fileName = 'github.png'; -//加密密钥 -var encryptKey = 'xxx'; -var query = { - 'name': 'qiniu', - 'location': 'shanghai' -}; var deadline = parseInt(Date.now() / 1000) + 3600; + var cdnManager = new qiniu.cdn.CdnManager(null); + var finalUrl = cdnManager.createTimestampAntiLeechUrl(domain, fileName, query, - encryptKey, - deadline); + encryptKey, deadline); + console.log(finalUrl); diff --git a/examples/cdn_get_bandwidth_data.js b/examples/cdn_get_bandwidth_data.js index 3fa88cf5..1071fecb 100644 --- a/examples/cdn_get_bandwidth_data.js +++ b/examples/cdn_get_bandwidth_data.js @@ -1,13 +1,13 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); -//域名列表 +// 域名列表 var domains = [ - 'if-pbl.qiniudn.com', - 'qdisk.qiniudn.com' + 'if-pbl.qiniudn.com', + 'qdisk.qiniudn.com' ]; -//指定日期 +// 指定日期 var startDate = '2017-06-20'; var endDate = '2017-06-22'; var granularity = 'day'; @@ -16,36 +16,36 @@ var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var cdnManager = new qiniu.cdn.CdnManager(mac); -//获取域名带宽 -cdnManager.getBandwidthData(startDate, endDate, granularity, domains, function( - err, respBody, respInfo) { - if (err) { - console.log(err); - throw err; - } +// 获取域名带宽 +cdnManager.getBandwidthData(startDate, endDate, granularity, domains, function ( + err, respBody, respInfo) { + if (err) { + console.log(err); + throw err; + } - console.log(respInfo.statusCode); - if (respInfo.statusCode == 200) { - var jsonBody = JSON.parse(respBody); - var code = jsonBody.code; - console.log(code); + console.log(respInfo.statusCode); + if (respInfo.statusCode == 200) { + var jsonBody = JSON.parse(respBody); + var code = jsonBody.code; + console.log(code); - var tickTime = jsonBody.time; - console.log(tickTime); + var tickTime = jsonBody.time; + console.log(tickTime); - var bandwidthData = jsonBody.data; - domains.forEach(function(domain) { - var bandwidthDataOfDomain = bandwidthData[domain]; - if (bandwidthDataOfDomain != null) { - console.log("bandwidth data for:" + domain); - var bandwidthChina = bandwidthDataOfDomain["china"]; - var bandwidthOversea = bandwidthDataOfDomain["oversea"]; - console.log(bandwidthChina); - console.log(bandwidthOversea); - } else { - console.log("no bandwidth data for:" + domain); - } - console.log("----------"); - }); - } + var bandwidthData = jsonBody.data; + domains.forEach(function (domain) { + var bandwidthDataOfDomain = bandwidthData[domain]; + if (bandwidthDataOfDomain != null) { + console.log('bandwidth data for:' + domain); + var bandwidthChina = bandwidthDataOfDomain.china; + var bandwidthOversea = bandwidthDataOfDomain.oversea; + console.log(bandwidthChina); + console.log(bandwidthOversea); + } else { + console.log('no bandwidth data for:' + domain); + } + console.log('----------'); + }); + } }); diff --git a/examples/cdn_get_flux_data.js b/examples/cdn_get_flux_data.js index 60af7b76..f0a361a2 100644 --- a/examples/cdn_get_flux_data.js +++ b/examples/cdn_get_flux_data.js @@ -1,13 +1,13 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); -//域名列表 +// 域名列表 var domains = [ - 'if-pbl.qiniudn.com', - 'qdisk.qiniudn.com' + 'if-pbl.qiniudn.com', + 'qdisk.qiniudn.com' ]; -//指定日期 +// 指定日期 var startDate = '2017-06-20'; var endDate = '2017-06-22'; var granularity = 'day'; @@ -16,35 +16,35 @@ var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var cdnManager = new qiniu.cdn.CdnManager(mac); -//获取域名流量 -cdnManager.getFluxData(startDate, endDate, granularity, domains, function(err, - respBody, respInfo) { - if (err) { - throw err; - } +// 获取域名流量 +cdnManager.getFluxData(startDate, endDate, granularity, domains, function (err, + respBody, respInfo) { + if (err) { + throw err; + } - console.log(respInfo.statusCode); - if (respInfo.statusCode == 200) { - var jsonBody = JSON.parse(respBody); - var code = jsonBody.code; - console.log(code); + console.log(respInfo.statusCode); + if (respInfo.statusCode == 200) { + var jsonBody = JSON.parse(respBody); + var code = jsonBody.code; + console.log(code); - var tickTime = jsonBody.time; - console.log(tickTime); + var tickTime = jsonBody.time; + console.log(tickTime); - var fluxData = jsonBody.data; - domains.forEach(function(domain) { - var fluxDataOfDomain = fluxData[domain]; - if (fluxDataOfDomain != null) { - console.log("flux data for:" + domain); - var fluxChina = fluxDataOfDomain["china"]; - var fluxOversea = fluxDataOfDomain["oversea"]; - console.log(fluxChina); - console.log(fluxOversea); - } else { - console.log("no flux data for:" + domain); - } - console.log("----------"); - }); - } + var fluxData = jsonBody.data; + domains.forEach(function (domain) { + var fluxDataOfDomain = fluxData[domain]; + if (fluxDataOfDomain != null) { + console.log('flux data for:' + domain); + var fluxChina = fluxDataOfDomain.china; + var fluxOversea = fluxDataOfDomain.oversea; + console.log(fluxChina); + console.log(fluxOversea); + } else { + console.log('no flux data for:' + domain); + } + console.log('----------'); + }); + } }); diff --git a/examples/cdn_get_log_list.js b/examples/cdn_get_log_list.js index 0cf22f4a..ab087314 100644 --- a/examples/cdn_get_log_list.js +++ b/examples/cdn_get_log_list.js @@ -1,27 +1,27 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); -//域名列表 +// 域名列表 var domains = [ - 'if-pbl.qiniudn.com', - 'qdisk.qiniudn.com' + 'if-pbl.qiniudn.com', + 'qdisk.qiniudn.com' ]; -//指定日期 +// 指定日期 var logDay = '2017-06-20'; var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var cdnManager = new qiniu.cdn.CdnManager(mac); -//获取域名日志 -cdnManager.getCdnLogList(domains, logDay, function(err, respBody, respInfo) { - if (err) { - throw err; - } +// 获取域名日志 +cdnManager.getCdnLogList(domains, logDay, function (err, respBody, respInfo) { + if (err) { + throw err; + } - console.log(respInfo.statusCode); - if (respInfo.statusCode == 200) { + console.log(respInfo.statusCode); + if (respInfo.statusCode == 200) { /** { "code":0, @@ -38,22 +38,22 @@ cdnManager.getCdnLogList(domains, logDay, function(err, respBody, respInfo) { } } */ - var jsonBody = JSON.parse(respBody); - var code = jsonBody.code; - console.log(code); - var logData = jsonBody.data; - domains.forEach(function(domain) { - console.log("log for domain: " + domain); - var domainLogs = logData[domain]; - if (domainLogs != null) { - domainLogs.forEach(function(logItem) { - console.log(logItem.name); - console.log(logItem.size); - console.log(logItem.mtime); - console.log(logItem.url); + var jsonBody = JSON.parse(respBody); + var code = jsonBody.code; + console.log(code); + var logData = jsonBody.data; + domains.forEach(function (domain) { + console.log('log for domain: ' + domain); + var domainLogs = logData[domain]; + if (domainLogs != null) { + domainLogs.forEach(function (logItem) { + console.log(logItem.name); + console.log(logItem.size); + console.log(logItem.mtime); + console.log(logItem.url); + }); + console.log('------------------'); + } }); - console.log("------------------"); - } - }); - } + } }); diff --git a/examples/cdn_prefetch_urls.js b/examples/cdn_prefetch_urls.js index 3ec9157b..7afb8507 100644 --- a/examples/cdn_prefetch_urls.js +++ b/examples/cdn_prefetch_urls.js @@ -1,33 +1,32 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); - -//URL 列表 +// URL 列表 var urlsToPrefetch = [ - 'http://if-pbl.qiniudn.com/nodejs.png', - 'http://if-pbl.qiniudn.com/qiniu.jpg' + 'http://if-pbl.qiniudn.com/nodejs.png', + 'http://if-pbl.qiniudn.com/qiniu.jpg' ]; var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var cdnManager = new qiniu.cdn.CdnManager(mac); -//预取链接 -cdnManager.prefetchUrls(urlsToPrefetch, function(err, respBody, respInfo) { - if (err) { - throw err; - } +// 预取链接 +cdnManager.prefetchUrls(urlsToPrefetch, function (err, respBody, respInfo) { + if (err) { + throw err; + } - console.log(respInfo.statusCode); - if (respInfo.statusCode == 200) { - var jsonBody = JSON.parse(respBody); - console.log(jsonBody.code); - console.log(jsonBody.error); - console.log(jsonBody.requestId); - console.log(jsonBody.invalidUrls); - console.log(jsonBody.invalidDirs); - console.log(jsonBody.urlQuotaDay); - console.log(jsonBody.urlSurplusDay); - console.log(jsonBody.dirQuotaDay); - console.log(jsonBody.dirSurplusDay); - } + console.log(respInfo.statusCode); + if (respInfo.statusCode == 200) { + var jsonBody = JSON.parse(respBody); + console.log(jsonBody.code); + console.log(jsonBody.error); + console.log(jsonBody.requestId); + console.log(jsonBody.invalidUrls); + console.log(jsonBody.invalidDirs); + console.log(jsonBody.urlQuotaDay); + console.log(jsonBody.urlSurplusDay); + console.log(jsonBody.dirQuotaDay); + console.log(jsonBody.dirSurplusDay); + } }); diff --git a/examples/cdn_refresh_urls_dirs.js b/examples/cdn_refresh_urls_dirs.js index 1a38cf65..2dd7bf65 100644 --- a/examples/cdn_refresh_urls_dirs.js +++ b/examples/cdn_refresh_urls_dirs.js @@ -1,84 +1,82 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); -//URL 列表 +// URL 列表 var urlsToRefresh = [ - 'http://if-pbl.qiniudn.com/nodejs.png', - 'http://if-pbl.qiniudn.com/qiniu.jpg' + 'http://if-pbl.qiniudn.com/nodejs.png', + 'http://if-pbl.qiniudn.com/qiniu.jpg' ]; -//DIR 列表 +// DIR 列表 var dirsToRefresh = [ - 'http://if-pbl.qiniudn.com/examples/', - 'http://if-pbl.qiniudn.com/images/' + 'http://if-pbl.qiniudn.com/examples/', + 'http://if-pbl.qiniudn.com/images/' ]; var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var cdnManager = new qiniu.cdn.CdnManager(mac); -//刷新链接 -cdnManager.refreshUrls(urlsToRefresh, function(err, respBody, respInfo) { - if (err) { - throw err; - } - - console.log(respInfo.statusCode); - if (respInfo.statusCode == 200) { - var jsonBody = JSON.parse(respBody); - console.log(jsonBody.code); - console.log(jsonBody.error); - console.log(jsonBody.requestId); - console.log(jsonBody.invalidUrls); - console.log(jsonBody.invalidDirs); - console.log(jsonBody.urlQuotaDay); - console.log(jsonBody.urlSurplusDay); - console.log(jsonBody.dirQuotaDay); - console.log(jsonBody.dirSurplusDay); - } - +// 刷新链接 +cdnManager.refreshUrls(urlsToRefresh, function (err, respBody, respInfo) { + if (err) { + throw err; + } + console.log(respInfo.statusCode); + if (respInfo.statusCode == 200) { + var jsonBody = JSON.parse(respBody); + console.log(jsonBody.code); + console.log(jsonBody.error); + console.log(jsonBody.requestId); + console.log(jsonBody.invalidUrls); + console.log(jsonBody.invalidDirs); + console.log(jsonBody.urlQuotaDay); + console.log(jsonBody.urlSurplusDay); + console.log(jsonBody.dirQuotaDay); + console.log(jsonBody.dirSurplusDay); + } }); -//刷新目录,刷新目录需要联系七牛技术支持开通权限 -cdnManager.refreshDirs(dirsToRefresh, function(err, respBody, respInfo) { - if (err) { - throw err; - } +// 刷新目录,刷新目录需要联系七牛技术支持开通权限 +cdnManager.refreshDirs(dirsToRefresh, function (err, respBody, respInfo) { + if (err) { + throw err; + } - console.log(respInfo.statusCode); - if (respInfo.statusCode == 200) { - var jsonBody = JSON.parse(respBody); - console.log(jsonBody.code); - console.log(jsonBody.error); - console.log(jsonBody.requestId); - console.log(jsonBody.invalidUrls); - console.log(jsonBody.invalidDirs); - console.log(jsonBody.urlQuotaDay); - console.log(jsonBody.urlSurplusDay); - console.log(jsonBody.dirQuotaDay); - console.log(jsonBody.dirSurplusDay); - } + console.log(respInfo.statusCode); + if (respInfo.statusCode == 200) { + var jsonBody = JSON.parse(respBody); + console.log(jsonBody.code); + console.log(jsonBody.error); + console.log(jsonBody.requestId); + console.log(jsonBody.invalidUrls); + console.log(jsonBody.invalidDirs); + console.log(jsonBody.urlQuotaDay); + console.log(jsonBody.urlSurplusDay); + console.log(jsonBody.dirQuotaDay); + console.log(jsonBody.dirSurplusDay); + } }); -//一起刷新 -cdnManager.refreshUrlsAndDirs(urlsToRefresh, dirsToRefresh, function(err, - respBody, respInfo) { - if (err) { - throw err; - } +// 一起刷新 +cdnManager.refreshUrlsAndDirs(urlsToRefresh, dirsToRefresh, function (err, + respBody, respInfo) { + if (err) { + throw err; + } - console.log(respInfo.statusCode); - if (respInfo.statusCode == 200) { - var jsonBody = JSON.parse(respBody); - console.log(jsonBody.code); - console.log(jsonBody.error); - console.log(jsonBody.requestId); - console.log(jsonBody.invalidUrls); - console.log(jsonBody.invalidDirs); - console.log(jsonBody.urlQuotaDay); - console.log(jsonBody.urlSurplusDay); - console.log(jsonBody.dirQuotaDay); - console.log(jsonBody.dirSurplusDay); - } + console.log(respInfo.statusCode); + if (respInfo.statusCode == 200) { + var jsonBody = JSON.parse(respBody); + console.log(jsonBody.code); + console.log(jsonBody.error); + console.log(jsonBody.requestId); + console.log(jsonBody.invalidUrls); + console.log(jsonBody.invalidDirs); + console.log(jsonBody.urlQuotaDay); + console.log(jsonBody.urlSurplusDay); + console.log(jsonBody.dirQuotaDay); + console.log(jsonBody.dirSurplusDay); + } }); diff --git a/examples/create_uptoken.js b/examples/create_uptoken.js index 384cb56f..e9005f4f 100644 --- a/examples/create_uptoken.js +++ b/examples/create_uptoken.js @@ -1,75 +1,74 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); -var bucket = 'if-pbl'; +var bucket = proc.env.QINIU_TEST_BUCKET; -//简单上传凭证 +// 简单上传凭证 var options = { - scope: bucket, + scope: bucket }; var putPolicy = new qiniu.rs.PutPolicy(options); console.log(putPolicy.uploadToken(mac)); -//自定义凭证有效期(示例2小时) -var options = { - scope: bucket, - expires: 7200 -} -var putPolicy = new qiniu.rs.PutPolicy(options); +// 自定义凭证有效期(示例2小时) +options = { + scope: bucket, + expires: 7200 +}; +putPolicy = new qiniu.rs.PutPolicy(options); console.log(putPolicy.uploadToken(mac)); // 覆盖上传凭证 var keyToOverwrite = 'qiniu.mp4'; -var options = { - scope: bucket + ":" + keyToOverwrite -} -var putPolicy = new qiniu.rs.PutPolicy(options); +options = { + scope: bucket + ':' + keyToOverwrite +}; +putPolicy = new qiniu.rs.PutPolicy(options); console.log(putPolicy.uploadToken(mac)); -//自定义上传回复(非callback模式)凭证 -var options = { - scope: bucket, - returnBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}' -} -var putPolicy = new qiniu.rs.PutPolicy(options); +// 自定义上传回复(非callback模式)凭证 +options = { + scope: bucket, + returnBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}' +}; +putPolicy = new qiniu.rs.PutPolicy(options); console.log(putPolicy.uploadToken(mac)); -//带回调业务服务器的凭证(application/json) -var options = { - scope: bucket, - callbackUrl: 'http://api.example.com/qiniu/upload/callback', - callbackBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}', - callbackBodyType: 'application/json' -} -var putPolicy = new qiniu.rs.PutPolicy(options); +// 带回调业务服务器的凭证(application/json) +options = { + scope: bucket, + callbackUrl: 'http://api.example.com/qiniu/upload/callback', + callbackBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}', + callbackBodyType: 'application/json' +}; +putPolicy = new qiniu.rs.PutPolicy(options); console.log(putPolicy.uploadToken(mac)); - -//带回调业务服务器的凭证(application/x-www-form-urlencoded) -var options = { - scope: bucket, - callbackUrl: 'http://api.example.com/qiniu/upload/callback', - callbackBody: 'key=$(key)&hash=$(etag)&bucket=$(bucket)&fsize=$(fsize)&name=$(x:name)' -} -var putPolicy = new qiniu.rs.PutPolicy(options); +// 带回调业务服务器的凭证(application/x-www-form-urlencoded) +options = { + scope: bucket, + callbackUrl: 'http://api.example.com/qiniu/upload/callback', + callbackBody: 'key=$(key)&hash=$(etag)&bucket=$(bucket)&fsize=$(fsize)&name=$(x:name)' +}; +putPolicy = new qiniu.rs.PutPolicy(options); console.log(putPolicy.uploadToken(mac)); -//带数据处理的凭证 +// 带数据处理的凭证 var saveMp4Entry = qiniu.util.urlsafeBase64Encode(bucket + - ":avthumb_test_target.mp4"); + ':avthumb_test_target.mp4'); var saveJpgEntry = qiniu.util.urlsafeBase64Encode(bucket + - ":vframe_test_target.jpg"); -var avthumbMp4Fop = "avthumb/mp4|saveas/" + saveMp4Entry; -var vframeJpgFop = "vframe/jpg/offset/1|saveas/" + saveJpgEntry; -var options = { - scope: bucket, - persistentOps: avthumbMp4Fop + ";" + vframeJpgFop, - persistentPipeline: "video-pipe", - persistentNotifyUrl: "http://api.example.com/qiniu/pfop/notify", -} -var putPolicy = new qiniu.rs.PutPolicy(options); + ':vframe_test_target.jpg'); +var avthumbMp4Fop = 'avthumb/mp4|saveas/' + saveMp4Entry; +var vframeJpgFop = 'vframe/jpg/offset/1|saveas/' + saveJpgEntry; +options = { + scope: bucket, + persistentOps: avthumbMp4Fop + ';' + vframeJpgFop, + persistentPipeline: 'video-pipe', + persistentNotifyUrl: 'http://api.example.com/qiniu/pfop/notify' +}; +putPolicy = new qiniu.rs.PutPolicy(options); console.log(putPolicy.uploadToken(mac)); diff --git a/examples/form_qvm_upload.js b/examples/form_qvm_upload.js new file mode 100644 index 00000000..24593d09 --- /dev/null +++ b/examples/form_qvm_upload.js @@ -0,0 +1,71 @@ +const qiniu = require('../index.js'); +const proc = require('process'); + +var bucket = proc.env.QINIU_TEST_BUCKET; +var accessKey = proc.env.QINIU_ACCESS_KEY; +var secretKey = proc.env.QINIU_SECRET_KEY; +var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); +var options = { + scope: bucket +}; +var putPolicy = new qiniu.rs.PutPolicy(options); + +var uploadToken = putPolicy.uploadToken(mac); +var config = new qiniu.conf.Config(); +var localFile = '/Users/jemy/Documents/qiniu.mp4'; +// config.zone = qiniu.zone.Zone_z0; + +// construct a new zone +// 华东 +var ZONE_QVM_Z0 = new qiniu.conf.Zone([ + 'free-qvm-z0-xs.qiniup.com' +], [ + 'free-qvm-z0-xs.qiniup.com' +], 'iovip.qbox.me', +'rs.qbox.me', +'rsf.qbox.me', +'api.qiniu.com'); + +// 华北 +var ZONE_QVM_Z1 = new qiniu.conf.Zone([ + 'free-qvm-z1-zz.qiniup.com' +], [ + 'free-qvm-z1-zz.qiniup.com' +], 'iovip-z1.qbox.me', +'rs-z1.qbox.me', +'rsf-z1.qbox.me', +'api-z1.qiniu.com'); + +config.zone = ZONE_QVM_Z0; +config.zone = ZONE_QVM_Z1; +var formUploader = new qiniu.form_up.FormUploader(config); +var putExtra = new qiniu.form_up.PutExtra(); +// bytes +formUploader.put(uploadToken, null, 'hello', null, function (respErr, + respBody, respInfo) { + if (respErr) { + throw respErr; + } + + if (respInfo.statusCode == 200) { + console.log(respBody); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } +}); + +// file +formUploader.putFile(uploadToken, null, localFile, putExtra, function (respErr, + respBody, respInfo) { + if (respErr) { + throw respErr; + } + + if (respInfo.statusCode == 200) { + console.log(respBody); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } +}); diff --git a/examples/form_upload_simple.js b/examples/form_upload_simple.js index c02a49e9..05c1a665 100644 --- a/examples/form_upload_simple.js +++ b/examples/form_upload_simple.js @@ -1,48 +1,68 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('../index.js'); +const proc = require('process'); -var bucket = 'if-pbl'; +var bucket = proc.env.QINIU_TEST_BUCKET; var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var options = { - scope: bucket, -} + scope: bucket +}; var putPolicy = new qiniu.rs.PutPolicy(options); var uploadToken = putPolicy.uploadToken(mac); var config = new qiniu.conf.Config(); -var localFile = "/Users/jemy/Documents/qiniu.mp4"; -//config.zone = qiniu.zone.Zone_z0; +var localFile = '/Users/jemy/Downloads/VIDEO_20191008_093955.mp4.zip'; +// config.zone = qiniu.zone.Zone_z0; var formUploader = new qiniu.form_up.FormUploader(config); var putExtra = new qiniu.form_up.PutExtra(); -//bytes -formUploader.put(uploadToken, null, "hello", null, function(respErr, - respBody, respInfo) { - if (respErr) { - throw respErr; - } +// bytes +// formUploader.put(uploadToken, null, "hello", null, function(respErr, +// respBody, respInfo) { +// if (respErr) { +// throw respErr; +// } +// +// if (respInfo.statusCode == 200) { +// console.log(respBody); +// } else { +// console.log(respInfo.statusCode); +// console.log(respBody); +// } +// }); + +// file +putExtra.fname = 'testfile16.mp4'; +formUploader.putFile(uploadToken, null, localFile, putExtra, function (respErr, + respBody, respInfo) { + if (respErr) { + throw respErr; + } - if (respInfo.statusCode == 200) { - console.log(respBody); - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } + if (respInfo.statusCode == 200) { + console.log(respBody); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } }); -//file -formUploader.putFile(uploadToken, null, localFile, putExtra, function(respErr, - respBody, respInfo) { - if (respErr) { - throw respErr; - } +// test query zone frequently when config.zone==null; +setTimeout(upload, 1500); +function upload () { + putExtra.fname = 'testfile17.mp4'; + formUploader.putFile(uploadToken, null, localFile, putExtra, function (respErr, + respBody, respInfo) { + if (respErr) { + throw respErr; + } - if (respInfo.statusCode == 200) { - console.log(respBody); - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } -}); + if (respInfo.statusCode == 200) { + console.log(respBody); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } + }); +} diff --git a/examples/http_https_proxy.js b/examples/http_https_proxy.js new file mode 100644 index 00000000..4cc88618 --- /dev/null +++ b/examples/http_https_proxy.js @@ -0,0 +1,51 @@ +const qiniu = require('qiniu'); +const proc = require('process'); +const tunnel = require('tunnel-agent'); + +var bucket = 'if-pbl'; +var accessKey = proc.env.QINIU_ACCESS_KEY; +var secretKey = proc.env.QINIU_SECRET_KEY; +var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); +var options = { + scope: bucket +}; +var putPolicy = new qiniu.rs.PutPolicy(options); + +var uploadToken = putPolicy.uploadToken(mac); +var config = new qiniu.conf.Config(); +// config.zone = qiniu.zone.Zone_z0; +// config.useHttpsDomain = true; +var formUploader = new qiniu.form_up.FormUploader(config); +var putExtra = new qiniu.form_up.PutExtra(); + +// 设置HTTP(s)代理服务器,这里可以参考:https://github.com/request/tunnel-agent +// 有几个方法: +// exports.httpOverHttp = httpOverHttp +// exports.httpsOverHttp = httpsOverHttp +// exports.httpOverHttps = httpOverHttps +// exports.httpsOverHttps = httpsOverHttps + +var proxyAgent = tunnel.httpOverHttp({ + proxy: { + host: 'localhost', + port: 8888 + } +}); + +qiniu.conf.RPC_HTTP_AGENT = proxyAgent; + +// qiniu.conf.RPC_HTTPS_AGENT = proxyAgent; +// 以代理方式上传 +formUploader.put(uploadToken, null, 'hello', putExtra, function (respErr, + respBody, respInfo) { + if (respErr) { + throw respErr; + } + + if (respInfo.statusCode == 200) { + console.log(respBody); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } +}); diff --git a/examples/pfops_video_plus.js b/examples/pfops_video_plus.js new file mode 100644 index 00000000..67648ecf --- /dev/null +++ b/examples/pfops_video_plus.js @@ -0,0 +1,62 @@ +var qiniu = require('qiniu'); +var urllib = require('urllib'); + +qiniu.conf.ACCESS_KEY = 'ak'; +qiniu.conf.SECRET_KEY = 'sk'; + +var url = 'http://argus.atlab.ai/v1/video/89999sssss'; + +var mac = new qiniu.auth.digest.Mac(qiniu.conf.ACCESS_KEY, qiniu.conf.SECRET_KEY); + +var json = { + + data: { + uri: 'http://test.qiniu.com/Videos/2016-09/39/9d019f7acab742ddbc5f4db02b6f72cb.mp4' + }, + params: { + async: false, + vframe: { + mode: 0, + interval: 5 + } + }, + ops: [ + { + op: 'pulp', + params: { + labels: [ + { + label: '1', + select: 2, + score: 0.0002 + }, + { + label: '2', + select: 2, + score: 0.0002 + } + + ] + } + } + ] +}; + +var accessToken = qiniu.util.generateAccessTokenV2(mac, url, 'POST', 'application/json', JSON.stringify(json)); + +urllib.request(url, { + method: 'POST', + headers: { + Authorization: accessToken, + 'Content-Type': 'application/json' + }, + data: JSON.stringify(json) +}, function (err, data, res) { + if (err) { + console.log(err); + throw err; // you need to handle error + } + console.log(res.statusCode); + console.log(res); + console.log(data.toString()); +}); diff --git a/examples/prefop.js b/examples/prefop.js index cd944328..8d330cd3 100644 --- a/examples/prefop.js +++ b/examples/prefop.js @@ -1,31 +1,31 @@ -const qiniu = require("qiniu"); +const qiniu = require('qiniu'); -//var persistentId = 'z0.594b66f745a2650c99aa9e57'; +// var persistentId = 'z0.594b66f745a2650c99aa9e57'; var persistentId = 'na0.58df4eee92129336c2075195'; var config = new qiniu.conf.Config(); config.useHttpsDomain = true; var operManager = new qiniu.fop.OperationManager(null, config); -//持久化数据处理返回的是任务的persistentId,可以根据这个id查询处理状态 -operManager.prefop(persistentId, function(err, respBody, respInfo) { - if (err) { - console.log(err); - throw err; - } +// 持久化数据处理返回的是任务的persistentId,可以根据这个id查询处理状态 +operManager.prefop(persistentId, function (err, respBody, respInfo) { + if (err) { + console.log(err); + throw err; + } - if (respInfo.statusCode == 200) { - console.log(respBody.inputBucket); - console.log(respBody.inputKey); - console.log(respBody.pipeline); - console.log(respBody.reqid); - respBody.items.forEach(function(item) { - console.log(item.cmd); - console.log(item.code); - console.log(item.desc); - console.log(item.hash); - console.log(item.key); - }); - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } + if (respInfo.statusCode == 200) { + console.log(respBody.inputBucket); + console.log(respBody.inputKey); + console.log(respBody.pipeline); + console.log(respBody.reqid); + respBody.items.forEach(function (item) { + console.log(item.cmd); + console.log(item.code); + console.log(item.desc); + console.log(item.hash); + console.log(item.key); + }); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/resume_upload_simple.js b/examples/resume_upload_simple.js index 67bf2dfa..3cbcf9b3 100644 --- a/examples/resume_upload_simple.js +++ b/examples/resume_upload_simple.js @@ -1,40 +1,43 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('../index.js'); +const proc = require('process'); -var bucket = 'if-pbl'; +var bucket = proc.env.QINIU_TEST_BUCKET; var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var options = { - scope: bucket, -} + scope: bucket +}; var putPolicy = new qiniu.rs.PutPolicy(options); var uploadToken = putPolicy.uploadToken(mac); var config = new qiniu.conf.Config(); -var localFile = "/Users/jemy/Documents/qiniu.mp4"; +var localFile = '/Users/jemy/Documents/qiniu.mp4'; config.zone = qiniu.zone.Zone_z0; config.useCdnDomain = true; var resumeUploader = new qiniu.resume_up.ResumeUploader(config); var putExtra = new qiniu.resume_up.PutExtra(); putExtra.params = { - "x:name": "", - "x:age": 27, -} + 'x:name': '', + 'x:age': 27 +}; putExtra.fname = 'testfile.mp4'; putExtra.resumeRecordFile = 'progress.log'; +putExtra.progressCallback = function (uploadBytes, totalBytes) { + console.log('progress:' + uploadBytes + '(' + totalBytes + ')'); +}; -//file -resumeUploader.putFile(uploadToken, null, localFile, putExtra, function(respErr, - respBody, respInfo) { - if (respErr) { - throw respErr; - } +// file +resumeUploader.putFile(uploadToken, null, localFile, putExtra, function (respErr, + respBody, respInfo) { + if (respErr) { + throw respErr; + } - if (respInfo.statusCode == 200) { - console.log(respBody); - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } + if (respInfo.statusCode == 200) { + console.log(respBody); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/rs_batch_change_type.js b/examples/rs_batch_change_type.js index f751060d..ceb47331 100644 --- a/examples/rs_batch_change_type.js +++ b/examples/rs_batch_change_type.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -7,33 +7,33 @@ var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = 'if-pbl'; +var srcBucket = proc.env.QINIU_TEST_BUCKET; -//每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 +// 每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 var changeTypeOperations = [ - qiniu.rs.changeTypeOp(srcBucket, 'qiniu1.mp4', 1), - qiniu.rs.changeTypeOp(srcBucket, 'qiniu2.mp4', 1), - qiniu.rs.changeTypeOp(srcBucket, 'qiniu3.mp4', 1), - qiniu.rs.changeTypeOp(srcBucket, 'qiniu4.mp4', 1), + qiniu.rs.changeTypeOp(srcBucket, 'qiniu1.mp4', 1), + qiniu.rs.changeTypeOp(srcBucket, 'qiniu2.mp4', 1), + qiniu.rs.changeTypeOp(srcBucket, 'qiniu3.mp4', 1), + qiniu.rs.changeTypeOp(srcBucket, 'qiniu4.mp4', 1) ]; -bucketManager.batch(changeTypeOperations, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { +bucketManager.batch(changeTypeOperations, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { // 200 is success, 298 is part success - if (parseInt(respInfo.statusCode / 100) == 2) { - respBody.forEach(function(item) { - if (item.code == 200) { - console.log("success"); + if (parseInt(respInfo.statusCode / 100) == 2) { + respBody.forEach(function (item) { + if (item.code == 200) { + console.log('success'); + } else { + console.log(item.code + '\t' + item.data.error); + } + }); } else { - console.log(item.code + "\t" + item.data.error); + console.log(respInfo.statusCode); + console.log(respBody); } - }); - } else { - console.log(respInfo.statusCode); - console.log(respBody); } - } }); diff --git a/examples/rs_batch_chgm.js b/examples/rs_batch_chgm.js index 6dd5455b..aa3aab4a 100644 --- a/examples/rs_batch_chgm.js +++ b/examples/rs_batch_chgm.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -7,33 +7,33 @@ var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = 'if-pbl'; +var srcBucket = proc.env.QINIU_TEST_BUCKET; -//每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 +// 每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 var chgmOperations = [ - qiniu.rs.changeMimeOp(srcBucket, 'qiniu1.mp4', 'video/x-mp4'), - qiniu.rs.changeMimeOp(srcBucket, 'qiniu2.mp4', 'video/x-mp4'), - qiniu.rs.changeMimeOp(srcBucket, 'qiniu3.mp4', 'video/x-mp4'), - qiniu.rs.changeMimeOp(srcBucket, 'qiniu4.mp4', 'video/x-mp4'), + qiniu.rs.changeMimeOp(srcBucket, 'qiniu1.mp4', 'video/x-mp4'), + qiniu.rs.changeMimeOp(srcBucket, 'qiniu2.mp4', 'video/x-mp4'), + qiniu.rs.changeMimeOp(srcBucket, 'qiniu3.mp4', 'video/x-mp4'), + qiniu.rs.changeMimeOp(srcBucket, 'qiniu4.mp4', 'video/x-mp4') ]; -bucketManager.batch(chgmOperations, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { +bucketManager.batch(chgmOperations, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { // 200 is success, 298 is part success - if (parseInt(respInfo.statusCode / 100) == 2) { - respBody.forEach(function(item) { - if (item.code == 200) { - console.log("success"); + if (parseInt(respInfo.statusCode / 100) == 2) { + respBody.forEach(function (item) { + if (item.code == 200) { + console.log('success'); + } else { + console.log(item.code + '\t' + item.data.error); + } + }); } else { - console.log(item.code + "\t" + item.data.error); + console.log(respInfo.statusCode); + console.log(respBody); } - }); - } else { - console.log(respInfo.statusCode); - console.log(respBody); } - } }); diff --git a/examples/rs_batch_copy.js b/examples/rs_batch_copy.js index bdfc3e3f..2d049530 100644 --- a/examples/rs_batch_copy.js +++ b/examples/rs_batch_copy.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -7,37 +7,37 @@ var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = 'if-pbl'; +var srcBucket = proc.env.QINIU_TEST_BUCKET; var srcKey = 'qiniu.mp4'; var destBucket = srcBucket; -//每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 +// 每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 var copyOperations = [ - qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu1.mp4', { - force: true - }), - qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu2.mp4'), - qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu3.mp4'), - qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu4.mp4'), + qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu1.mp4', { + force: true + }), + qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu2.mp4'), + qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu3.mp4'), + qiniu.rs.copyOp(srcBucket, srcKey, destBucket, 'qiniu4.mp4') ]; -bucketManager.batch(copyOperations, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { +bucketManager.batch(copyOperations, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { // 200 is success, 298 is part success - if (parseInt(respInfo.statusCode / 100) == 2) { - respBody.forEach(function(item) { - if (item.code == 200) { - console.log(item.code + "\tsuccess"); + if (parseInt(respInfo.statusCode / 100) == 2) { + respBody.forEach(function (item) { + if (item.code == 200) { + console.log(item.code + '\tsuccess'); + } else { + console.log(item.code + '\t' + item.data.error); + } + }); } else { - console.log(item.code + "\t" + item.data.error); + console.log(respInfo.deleteusCode); + console.log(respBody); } - }); - } else { - console.log(respInfo.deleteusCode); - console.log(respBody); } - } }); diff --git a/examples/rs_batch_delete.js b/examples/rs_batch_delete.js index 840aace8..8e6e218c 100644 --- a/examples/rs_batch_delete.js +++ b/examples/rs_batch_delete.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -7,33 +7,33 @@ var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = 'if-pbl'; +var srcBucket = proc.env.QINIU_TEST_BUCKET; -//每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 +// 每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 var deleteOperations = [ - qiniu.rs.deleteOp(srcBucket, 'qiniu1.mp4'), - qiniu.rs.deleteOp(srcBucket, 'qiniu2.mp4'), - qiniu.rs.deleteOp(srcBucket, 'qiniu3.mp4'), - qiniu.rs.deleteOp(srcBucket, 'qiniu4x.mp4'), + qiniu.rs.deleteOp(srcBucket, 'qiniu1.mp4'), + qiniu.rs.deleteOp(srcBucket, 'qiniu2.mp4'), + qiniu.rs.deleteOp(srcBucket, 'qiniu3.mp4'), + qiniu.rs.deleteOp(srcBucket, 'qiniu4x.mp4') ]; -bucketManager.batch(deleteOperations, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { +bucketManager.batch(deleteOperations, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { // 200 is success, 298 is part success - if (parseInt(respInfo.statusCode / 100) == 2) { - respBody.forEach(function(item) { - if (item.code == 200) { - console.log(item.code + "\tsuccess"); + if (parseInt(respInfo.statusCode / 100) == 2) { + respBody.forEach(function (item) { + if (item.code == 200) { + console.log(item.code + '\tsuccess'); + } else { + console.log(item.code + '\t' + item.data.error); + } + }); } else { - console.log(item.code + "\t" + item.data.error); + console.log(respInfo.deleteusCode); + console.log(respBody); } - }); - } else { - console.log(respInfo.deleteusCode); - console.log(respBody); } - } }); diff --git a/examples/rs_batch_delete_after_days.js b/examples/rs_batch_delete_after_days.js index 7d45856a..53d3e023 100644 --- a/examples/rs_batch_delete_after_days.js +++ b/examples/rs_batch_delete_after_days.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -7,33 +7,33 @@ var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = 'if-pbl'; +var srcBucket = proc.env.QINIU_TEST_BUCKET; -//每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 +// 每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 var deleteAfterDaysOperations = [ - qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu1.mp4', 10), - qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu2.mp4', 10), - qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu3.mp4', 10), - qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu4.mp4', 10), + qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu1.mp4', 10), + qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu2.mp4', 10), + qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu3.mp4', 10), + qiniu.rs.deleteAfterDaysOp(srcBucket, 'qiniu4.mp4', 10) ]; -bucketManager.batch(deleteAfterDaysOperations, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { +bucketManager.batch(deleteAfterDaysOperations, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { // 200 is success, 298 is part success - if (parseInt(respInfo.statusCode / 100) == 2) { - respBody.forEach(function(item) { - if (item.code == 200) { - console.log("success"); + if (parseInt(respInfo.statusCode / 100) == 2) { + respBody.forEach(function (item) { + if (item.code == 200) { + console.log('success'); + } else { + console.log(item.code + '\t' + item.data.error); + } + }); } else { - console.log(item.code + "\t" + item.data.error); + console.log(respInfo.statusCode); + console.log(respBody); } - }); - } else { - console.log(respInfo.statusCode); - console.log(respBody); } - } }); diff --git a/examples/rs_batch_move.js b/examples/rs_batch_move.js index e703b7a9..b262456e 100644 --- a/examples/rs_batch_move.js +++ b/examples/rs_batch_move.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -7,34 +7,34 @@ var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = 'if-pbl'; +var srcBucket = proc.env.QINIU_TEST_BUCKET; var destBucket = srcBucket; -//每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 +// 每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 var moveOperations = [ - qiniu.rs.moveOp(srcBucket, 'qiniu1.mp4', destBucket, 'qiniu1_move.mp4'), - qiniu.rs.moveOp(srcBucket, 'qiniu2.mp4', destBucket, 'qiniu2_move.mp4'), - qiniu.rs.moveOp(srcBucket, 'qiniu3.mp4', destBucket, 'qiniu3_move.mp4'), - qiniu.rs.moveOp(srcBucket, 'qiniu4.mp4', destBucket, 'qiniu4_move.mp4'), + qiniu.rs.moveOp(srcBucket, 'qiniu1.mp4', destBucket, 'qiniu1_move.mp4'), + qiniu.rs.moveOp(srcBucket, 'qiniu2.mp4', destBucket, 'qiniu2_move.mp4'), + qiniu.rs.moveOp(srcBucket, 'qiniu3.mp4', destBucket, 'qiniu3_move.mp4'), + qiniu.rs.moveOp(srcBucket, 'qiniu4.mp4', destBucket, 'qiniu4_move.mp4') ]; -bucketManager.batch(moveOperations, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { +bucketManager.batch(moveOperations, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { // 200 is success, 298 is part success - if (parseInt(respInfo.statusCode / 100) == 2) { - respBody.forEach(function(item) { - if (item.code == 200) { - console.log(item.code + "\tsuccess"); + if (parseInt(respInfo.statusCode / 100) == 2) { + respBody.forEach(function (item) { + if (item.code == 200) { + console.log(item.code + '\tsuccess'); + } else { + console.log(item.code + '\t' + item.data.error); + } + }); } else { - console.log(item.code + "\t" + item.data.error); + console.log(respInfo.deleteusCode); + console.log(respBody); } - }); - } else { - console.log(respInfo.deleteusCode); - console.log(respBody); } - } }); diff --git a/examples/rs_batch_stat.js b/examples/rs_batch_stat.js index 702913d6..163810f8 100644 --- a/examples/rs_batch_stat.js +++ b/examples/rs_batch_stat.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -7,35 +7,35 @@ var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = 'if-pbl'; +var srcBucket = proc.env.QINIU_TEST_BUCKET; -//每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 +// 每个operations的数量不可以超过1000个,如果总数量超过1000,需要分批发送 var statOperations = [ - qiniu.rs.statOp(srcBucket, 'qiniu1.mp4'), - qiniu.rs.statOp(srcBucket, 'qiniu2.mp4'), - qiniu.rs.statOp(srcBucket, 'qiniu3.mp4'), - qiniu.rs.statOp(srcBucket, 'qiniu4x.mp4'), + qiniu.rs.statOp(srcBucket, 'qiniu1.mp4'), + qiniu.rs.statOp(srcBucket, 'qiniu2.mp4'), + qiniu.rs.statOp(srcBucket, 'qiniu3.mp4'), + qiniu.rs.statOp(srcBucket, 'qiniu4x.mp4') ]; -bucketManager.batch(statOperations, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { +bucketManager.batch(statOperations, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { // 200 is success, 298 is part success - if (parseInt(respInfo.statusCode / 100) == 2) { - respBody.forEach(function(item) { - if (item.code == 200) { - console.log(item.data.fsize + "\t" + item.data.hash + "\t" + - item.data.mimeType + "\t" + item.data.putTime + "\t" + + if (parseInt(respInfo.statusCode / 100) == 2) { + respBody.forEach(function (item) { + if (item.code == 200) { + console.log(item.data.fsize + '\t' + item.data.hash + '\t' + + item.data.mimeType + '\t' + item.data.putTime + '\t' + item.data.type); + } else { + console.log(item.code + '\t' + item.data.error); + } + }); } else { - console.log(item.code + "\t" + item.data.error); + console.log(respInfo.statusCode); + console.log(respBody); } - }); - } else { - console.log(respInfo.statusCode); - console.log(respBody); } - } }); diff --git a/examples/rs_bucket_info.js b/examples/rs_bucket_info.js new file mode 100644 index 00000000..3561f828 --- /dev/null +++ b/examples/rs_bucket_info.js @@ -0,0 +1,24 @@ +const qiniu = require('qiniu'); +const proc = require('process'); + +var accessKey = proc.env.QINIU_ACCESS_KEY; +var secretKey = proc.env.QINIU_SECRET_KEY; + +var bucket = proc.env.QINIU_TEST_BUCKET; + +var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); +var config = new qiniu.conf.Config(); +config.zone = qiniu.zone.Zone_z0; +config.useHttpsDomain = 'https'; +var bucketManager = new qiniu.rs.BucketManager(mac, config); +// @param bucketName 空间名 +bucketManager.getBucketInfo(bucket, function (err, respBody, respInfo) { + if (err) { + console.log(err); + throw err; + } + if (respInfo.status == 200) { + console.log('---respBody\n' + JSON.stringify(respBody) + '\n---'); + console.log('---respInfo\n' + JSON.stringify(respInfo) + '\n---'); + } +}); diff --git a/examples/rs_change_mime.js b/examples/rs_change_mime.js index 4e632f05..31219785 100644 --- a/examples/rs_change_mime.js +++ b/examples/rs_change_mime.js @@ -1,24 +1,24 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = 'if-pbl'; +var bucket = proc.env.QINIU_TEST_BUCKET; var key = 'qiniu.mp4'; var newMime = 'video/x-mp4'; -bucketManager.changeMime(bucket, key, newMime, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - //200 is success - console.log(respInfo.statusCode); - console.log(respBody); - } +bucketManager.changeMime(bucket, key, newMime, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + // 200 is success + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/rs_change_type.js b/examples/rs_change_type.js index d059dd7b..0807d810 100644 --- a/examples/rs_change_type.js +++ b/examples/rs_change_type.js @@ -1,24 +1,24 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = 'if-pbl'; +var bucket = proc.env.QINIU_TEST_BUCKET; var key = 'qiniu.mp4'; -var newType = 1; //低频存储 +var newType = 1; // 低频存储 -bucketManager.changeType(bucket, key, newType, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - //200 is success - console.log(respInfo.statusCode); - console.log(respBody); - } +bucketManager.changeType(bucket, key, newType, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + // 200 is success + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/rs_copy.js b/examples/rs_copy.js index 7ff403b9..2c972e30 100644 --- a/examples/rs_copy.js +++ b/examples/rs_copy.js @@ -1,30 +1,29 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = "if-pbl"; -var srcKey = "qiniu.mp4"; -var destBucket = "if-pbl"; -var destKey = "qiniu_new_copy.mp4"; +var srcBucket = proc.env.QINIU_TEST_BUCKET; +var srcKey = 'qiniu.mp4'; +var destBucket = 'destBucket'; +var destKey = 'qiniu_new_copy.mp4'; var options = { - force: true -} - -bucketManager.copy(srcBucket, srcKey, destBucket, destKey, options, function( - err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - //200 is success - console.log(respInfo.statusCode); - console.log(respBody); - } + force: true +}; +bucketManager.copy(srcBucket, srcKey, destBucket, destKey, options, function ( + err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + // 200 is success + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/rs_delete.js b/examples/rs_delete.js index 61c6beae..58e72c79 100644 --- a/examples/rs_delete.js +++ b/examples/rs_delete.js @@ -1,22 +1,22 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = "if-pbl"; -var key = "qiniu_new_copy.mp4"; +var bucket = proc.env.QINIU_TEST_BUCKET; +var key = 'qiniu_new_copy.mp4'; -bucketManager.delete(bucket, key, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } +bucketManager.delete(bucket, key, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/rs_delete_after_days.js b/examples/rs_delete_after_days.js index 1ff25c8a..97ba55e1 100644 --- a/examples/rs_delete_after_days.js +++ b/examples/rs_delete_after_days.js @@ -1,24 +1,24 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = "if-pbl"; -var key = "qiniu_new_copy.mp4"; +var bucket = proc.env.QINIU_TEST_BUCKET; +var key = 'qiniu_new_copy.mp4'; var days = 10; -bucketManager.deleteAfterDays(bucket, key, days, function(err, respBody, - respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } +bucketManager.deleteAfterDays(bucket, key, days, function (err, respBody, + respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/rs_download.js b/examples/rs_download.js index 010700bd..71d05657 100644 --- a/examples/rs_download.js +++ b/examples/rs_download.js @@ -1,5 +1,5 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; @@ -10,13 +10,13 @@ var publicBucketDomain = 'http://if-pbl.qiniudn.com'; var privateBucketDomain = 'http://if-pri.qiniudn.com'; var key = 'qiniu.mp4'; -//public +// public var publicDownloadUrl = bucketManager.publicDownloadUrl(publicBucketDomain, key); console.log(publicDownloadUrl); -//private -var deadline = parseInt(Date.now() / 1000) + 3600; //1小时过期 +// private +var deadline = parseInt(Date.now() / 1000) + 3600; // 1小时过期 var privateDownloadUrl = bucketManager.privateDownloadUrl(privateBucketDomain, - key, - deadline); + key, + deadline); console.log(privateDownloadUrl); diff --git a/examples/rs_fetch.js b/examples/rs_fetch.js index d5d76104..fd6db397 100644 --- a/examples/rs_fetch.js +++ b/examples/rs_fetch.js @@ -1,30 +1,30 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; -//config.zone = qiniu.zone.Zone_z1; +// config.useHttpsDomain = true; +// config.zone = qiniu.zone.Zone_z1; var bucketManager = new qiniu.rs.BucketManager(mac, config); var resUrl = 'http://devtools.qiniu.com/qiniu.png'; -var bucket = "if-bc"; -var key = "qiniu.png"; +var bucket = proc.env.QINIU_TEST_BUCKET; +var key = 'qiniu.png'; -bucketManager.fetch(resUrl, bucket, key, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - if (respInfo.statusCode == 200) { - console.log(respBody.key); - console.log(respBody.hash); - console.log(respBody.fsize); - console.log(respBody.mimeType); +bucketManager.fetch(resUrl, bucket, key, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; } else { - console.log(respInfo.statusCode); - console.log(respBody); + if (respInfo.statusCode == 200) { + console.log(respBody.key); + console.log(respBody.hash); + console.log(respBody.fsize); + console.log(respBody.mimeType); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } } - } }); diff --git a/examples/rs_list_prefix.js b/examples/rs_list_prefix.js index 9d96fe30..ed8d0920 100644 --- a/examples/rs_list_prefix.js +++ b/examples/rs_list_prefix.js @@ -1,50 +1,50 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = 'if-pbl'; +var bucket = proc.env.QINIU_TEST_BUCKET; // @param options 列举操作的可选参数 // prefix 列举的文件前缀 // marker 上一次列举返回的位置标记,作为本次列举的起点信息 // limit 每次返回的最大列举文件数量 // delimiter 指定目录分隔符 var options = { - limit: 10, - prefix: 'calculus', + limit: 10, + prefix: 'calculus' }; -bucketManager.listPrefix(bucket, options, function(err, respBody, respInfo) { - if (err) { - console.log(err); - throw err; - } +bucketManager.listPrefix(bucket, options, function (err, respBody, respInfo) { + if (err) { + console.log(err); + throw err; + } - if (respInfo.statusCode == 200) { - //如果这个nextMarker不为空,那么还有未列举完毕的文件列表,下次调用listPrefix的时候, - //指定options里面的marker为这个值 - var nextMarker = respBody.marker; - var commonPrefixes = respBody.commonPrefixes; - console.log(nextMarker); - console.log(commonPrefixes); - var items = respBody.items; - items.forEach(function(item) { - console.log(item.key); - // console.log(item.putTime); - // console.log(item.hash); - // console.log(item.fsize); - // console.log(item.mimeType); - // console.log(item.endUser); - // console.log(item.type); - }); - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } + if (respInfo.statusCode == 200) { + // 如果这个nextMarker不为空,那么还有未列举完毕的文件列表,下次调用listPrefix的时候, + // 指定options里面的marker为这个值 + var nextMarker = respBody.marker; + var commonPrefixes = respBody.commonPrefixes; + console.log(nextMarker); + console.log(commonPrefixes); + var items = respBody.items; + items.forEach(function (item) { + console.log(item.key); + // console.log(item.putTime); + // console.log(item.hash); + // console.log(item.fsize); + // console.log(item.mimeType); + // console.log(item.endUser); + // console.log(item.type); + }); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/examples/rs_listv2.js b/examples/rs_listv2.js new file mode 100644 index 00000000..97486e73 --- /dev/null +++ b/examples/rs_listv2.js @@ -0,0 +1,31 @@ +const qiniu = require('qiniu'); +const proc = require('process'); + +var accessKey = proc.env.QINIU_ACCESS_KEY; +var secretKey = proc.env.QINIU_SECRET_KEY; +var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); +var config = new qiniu.conf.Config(); +// config.useHttpsDomain = true; +config.zone = qiniu.zone.Zone_z0; +var bucketManager = new qiniu.rs.BucketManager(mac, config); +var srcBucket = proc.env.QINIU_TEST_BUCKET; +// @param options 列举操作的可选参数 +// prefix 列举的文件前缀 +// marker 上一次列举返回的位置标记,作为本次列举的起点信息 +// limit 每次返回的最大列举文件数量 +// delimiter 指定目录分隔符 +var options = { + limit: 20 +}; + +bucketManager.listPrefixV2(srcBucket, options, function (err, respBody, respInfo) { + // the irregular data return from Server that Cannot be converted by urllib to JSON Object + // so err !=null and you can judge if err.res.statusCode==200 + if (err.res.statusCode != 200) { + console.log(err); + throw err; + } + + console.log('---respBody\n' + respBody + '\n---'); + console.log('---respInfo\n' + JSON.stringify(respInfo) + '\n---'); +}); diff --git a/examples/rs_move.js b/examples/rs_move.js index 36ea6241..48fed382 100644 --- a/examples/rs_move.js +++ b/examples/rs_move.js @@ -1,28 +1,27 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var srcBucket = "if-pbl"; -var srcKey = "qiniu.mp4"; -var destBucket = "if-pbl"; -var destKey = "qiniu_new.mp4"; +var srcBucket = proc.env.QINIU_TEST_BUCKET; +var srcKey = 'qiniu.mp4'; +var destBucket = srcBucket; +var destKey = 'qiniu_new.mp4'; var options = { - force: true -} -bucketManager.move(srcBucket, srcKey, destBucket, destKey, options, function( - err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - //200 is success - console.log(respInfo.statusCode); - } - + force: true +}; +bucketManager.move(srcBucket, srcKey, destBucket, destKey, options, function ( + err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + // 200 is success + console.log(respInfo.statusCode); + } }); diff --git a/examples/rs_prefetch.js b/examples/rs_prefetch.js index 47faf2ff..06ae555f 100644 --- a/examples/rs_prefetch.js +++ b/examples/rs_prefetch.js @@ -1,22 +1,22 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z1; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = "if-bc"; -var key = "qiniu.mp4"; +var bucket = proc.env.QINIU_TEST_BUCKET; +var key = 'qiniu.mp4'; -bucketManager.prefetch(bucket, key, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - //200 is success - console.log(respInfo.statusCode); - } +bucketManager.prefetch(bucket, key, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; + } else { + // 200 is success + console.log(respInfo.statusCode); + } }); diff --git a/examples/rs_stat.js b/examples/rs_stat.js index 60773c36..b57dcee1 100644 --- a/examples/rs_stat.js +++ b/examples/rs_stat.js @@ -1,31 +1,30 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; var bucketManager = new qiniu.rs.BucketManager(mac, config); -var bucket = "if-pbl"; -var key = "qiniux.mp4"; +var bucket = proc.env.QINIU_TEST_BUCKET; +var key = 'qiniux.mp4'; -bucketManager.stat(bucket, key, function(err, respBody, respInfo) { - if (err) { - console.log(err); - //throw err; - } else { - if (respInfo.statusCode == 200) { - console.log(respBody.hash); - console.log(respBody.fsize); - console.log(respBody.mimeType); - console.log(respBody.putTime); - console.log(respBody.type); +bucketManager.stat(bucket, key, function (err, respBody, respInfo) { + if (err) { + console.log(err); + // throw err; } else { - console.log(respInfo.statusCode); - console.log(respBody.error); + if (respInfo.statusCode == 200) { + console.log(respBody.hash); + console.log(respBody.fsize); + console.log(respBody.mimeType); + console.log(respBody.putTime); + console.log(respBody.type); + } else { + console.log(respInfo.statusCode); + console.log(respBody.error); + } } - } - }); diff --git a/examples/rs_upload_token.js b/examples/rs_upload_token.js index af06818a..2b92339b 100644 --- a/examples/rs_upload_token.js +++ b/examples/rs_upload_token.js @@ -1,11 +1,12 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; +var bucket = proc.env.QINIU_TEST_BUCKET; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var putPolicy = new qiniu.rs.PutPolicy({ - scope: 'if-pbl' + scope: bucket }); var uploadToken = putPolicy.uploadToken(mac); diff --git a/examples/rtc_demo.js b/examples/rtc_demo.js new file mode 100644 index 00000000..6fc6acfb --- /dev/null +++ b/examples/rtc_demo.js @@ -0,0 +1,98 @@ +const qiniu = require('../index.js'); + +// ak, sk 获取参考 https://developer.qiniu.com/dora/kb/3702/QiniuToken +var ACCESS_KEY = 'ak'; +var SECRET_KEY = 'sk'; +var credentials = new qiniu.Credentials(ACCESS_KEY, SECRET_KEY); + +// 参考 https://github.com/pili-engineering/QNRTC-Server/blob/master/docs/api.md + +var data = { + hub: 'your hub', + title: 'your title', + maxUsers: 10, + noAutoKickUser: true +}; + +qiniu.app.createApp(data, credentials, function (err, res) { + if (err) { + console.log(err); + } else { + console.log(res); + } +}); + +qiniu.app.getApp('appId', credentials, function (err, res) { + if (err) { + console.log(err); + } else { + console.log(res); + } +}); + +qiniu.app.deleteApp('appId', credentials, function (err, res) { + if (err) { + console.log(err); + } else { + console.log(res); + } +}); + +var data1 = { + hub: 'your hub', + title: 'your title', + maxUsers: 10, + noAutoKickUser: true, + mergePublishRtmp: { + enable: true, + audioOnly: true, + height: 1920, + width: 1080, + fps: 60, + kbps: 1000, + url: 'rtmp://xxx.example.com/test', + streamTitle: 'meeting' + } +}; +qiniu.app.updateApp('appId', data1, credentials, function (err, res) { + if (err) { + console.log(err); + } else { + console.log(res); + } +}); +qiniu.room.listUser('appId', 'roomName', credentials, function (err, res) { + if (err) { + console.log(err); + } else { + console.log(res); + } +}); + +qiniu.room.kickUser('appId', 'roomName', 'userId', credentials, function (err, res) { + if (err) { + console.log(err); + } else { + console.log(res); + } +}); + +// type of(offset limit) = Num such as 5 10 +qiniu.room.listActiveRooms('appId', 'prefix', 'offset', 'limit', credentials, function (err, res) { + if (err) { + console.log(err); + } else { + console.log(res); + } +}); + +// expireAt = 1524128577 or empty +var roomAccess = { + appId: 'your appId', + roomName: 'your roomName', + userId: 'userId', + expireAt: 1524128577, + permission: 'admin' +}; + +console.log(qiniu.room.getRoomToken(roomAccess, credentials)); diff --git a/examples/video_pfop.js b/examples/video_pfop.js index fcde7047..ee876602 100644 --- a/examples/video_pfop.js +++ b/examples/video_pfop.js @@ -1,43 +1,43 @@ -const qiniu = require("qiniu"); -const proc = require("process"); +const qiniu = require('qiniu'); +const proc = require('process'); var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); -//config.useHttpsDomain = true; +// config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z1; var operManager = new qiniu.fop.OperationManager(mac, config); -//处理指令集合 -var saveBucket = 'if-bc'; +// 处理指令集合 +var saveBucket = proc.env.QINIU_TEST_BUCKET; var fops = [ - 'avthumb/mp4/s/480x320/vb/150k|saveas/' + qiniu.util.urlsafeBase64Encode( - saveBucket + ":qiniu_480x320.mp4"), - 'vframe/jpg/offset/10|saveas/' + qiniu.util.urlsafeBase64Encode(saveBucket + - ":qiniu_frame1.jpg") + 'avthumb/mp4/s/480x320/vb/150k|saveas/' + qiniu.util.urlsafeBase64Encode( + saveBucket + ':qiniu_480x320.mp4'), + 'vframe/jpg/offset/10|saveas/' + qiniu.util.urlsafeBase64Encode(saveBucket + + ':qiniu_frame1.jpg') ]; var pipeline = 'jemy'; var srcBucket = 'if-bc'; var srcKey = 'qiniu.mp4'; var options = { - 'notifyURL': 'http://api.example.com/pfop/callback', - 'force': false, + notifyURL: 'http://api.example.com/pfop/callback', + force: false }; -//持久化数据处理返回的是任务的persistentId,可以根据这个id查询处理状态 -operManager.pfop(srcBucket, srcKey, fops, pipeline, options, function(err, - respBody, - respInfo) { - if (err) { - throw err; - } +// 持久化数据处理返回的是任务的persistentId,可以根据这个id查询处理状态 +operManager.pfop(srcBucket, srcKey, fops, pipeline, options, function (err, + respBody, + respInfo) { + if (err) { + throw err; + } - if (respInfo.statusCode == 200) { - console.log(respBody.persistentId); - } else { - console.log(respInfo.statusCode); - console.log(respBody); - } + if (respInfo.statusCode == 200) { + console.log(respBody.persistentId); + } else { + console.log(respInfo.statusCode); + console.log(respBody); + } }); diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 00000000..1abb9b01 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,744 @@ +/** + * typescript definition for qiniu 7.0.2 + * @date 2017-06-27 + * @author xialeistudio + */ +export declare type callback = (e?: Error, respBody?: any, respInfo?: any) => void; + +export declare namespace auth { + namespace digest { + class Mac { + accessKey: string; + secretKey: string; + + constructor(accessKey?: string, secretKey?: string); + } + } +} + +export declare namespace cdn { + class CdnManager { + mac: auth.digest.Mac; + + constructor(mac?: auth.digest.Mac); + + /** + * 获取域名日志下载链接 + * @see http://developer.qiniu.com/article/fusion/api/log.html + * + * @param domains 域名列表 如:['obbid7qc6.qnssl.com','7xkh68.com1.z0.glb.clouddn.com'] + * @param logDay logDay 如 2016-07-01 + * @param callback callbackFunc(err, respBody, respInfo) + */ + getCdnLogList(domains: string[], logDay: string, callback: callback): void; + + /** + * 获取域名访问流量数据 + * @see http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html#batch-flux + * + * @param startDate 开始日期,例如:2016-07-01 + * @param endDate 结束日期,例如:2016-07-03 + * @param granularity 粒度,取值:5min/hour/day + * @param domains 域名列表 domain = ['obbid7qc6.qnssl.com','obbid7qc6.qnssl.com']; + * @param callback callbackFunc(err, respBody, respInfo) + */ + getFluxData(startDate: string, endDate: string, granularity: string, domains: string[], callback: callback): void; + + /** + * 获取域名带宽数据 + * @see http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html#batch-flux + * @param startDate 开始日期,例如:2016-07-01 + * @param endDate 结束日期,例如:2016-07-03 + * @param granularity 粒度,取值:5min/hour/day + * @param domains 域名列表 domain = ['obbid7qc6.qnssl.com','obbid7qc6.qnssl.com']; + * @param callback callbackFunc(err, respBody, respInfo) + */ + getBandwidthData(startDate: string, endDate: string, granularity: string, domains: string[], callback: callback): void; + + /** + * 预取文件链接 + * @see http://developer.qiniu.com/article/fusion/api/prefetch.html + * + * @param urls 预取urls urls = ['http://obbid7qc6.qnssl.com/023','http://obbid7qc6.qnssl.com/025'] + * @param callback callbackFunc(err, respBody, respInfo) + */ + prefetchUrls(urls: string[], callback: callback): void; + + /** + * 刷新链接 + * @see http://developer.qiniu.com/article/fusion/api/refresh.html + * + * @param urls refreshUrls = ['http://obbid7qc6.qnssl.com/023','http://obbid7qc6.qnssl.com/025'] + * @param callback callbackFunc(err, respBody, respInfo) + */ + refreshUrls(urls: string[], callback: callback): void; + + /** + * 刷新目录列表,每次最多不可以超过10个目录, 刷新目录需要额外开通权限,可以联系七牛技术支持处理 + * @see http://developer.qiniu.com/article/fusion/api/refresh.html + * + * @param dirs refreshDirs = ['http://obbid7qc6.qnssl.com/wo/','http://obbid7qc6.qnssl.com/'] + * @param callback callbackFunc(err, respBody, respInfo) + */ + refreshDirs(dirs: string[], callback: callback): void; + + /** + * 刷新目录和链接 + * @param urls refreshUrls = ['http://obbid7qc6.qnssl.com/023','http://obbid7qc6.qnssl.com/025'] + * @param dirs refreshDirs = ['http://obbid7qc6.qnssl.com/wo/','http://obbid7qc6.qnssl.com/'] + * @param callback callbackFunc(err, respBody, respInfo) + */ + refreshUrlsAndDirs(urls: string[], dirs: string[], callback: callback): void; + + /** + * 构建标准的基于时间戳的防盗链 + * @param domain 自定义域名,例如 http://img.abc.com + * @param fileName 待访问的原始文件名,必须是utf8编码,不需要进行urlencode + * @param query 业务自身的查询参数,必须是utf8编码,不需要进行urlencode, 例如 {aa:"23", attname:"11111111111111"} + * @param encryptKey 时间戳防盗链的签名密钥,从七牛后台获取 + * @param deadline 链接的有效期时间戳,是以秒为单位的Unix时间戳 + * @return signedUrl 最终的带时间戳防盗链的url + */ + createTimestampAntiLeechUrl(domain: string, fileName: string, query: any, encryptKey: string, deadline: number): string; + } +} + +export declare namespace conf { + let ACCESS_KEY: string; + let SECRET_KEY: string; + let USER_AGENT: string; + let BLOCK_SIZE: number; + let FormMimeUrl: string; + let FormMimeJson: string; + let FormMimeRaw: string; + let RS_HOST: string; + let RPC_TIMEOUT: number; + + interface ConfigOptions { + /** + * @default false + */ + useHttpsDomain?: boolean; + + /** + * @default true + */ + useCdnDomain?: boolean; + + /** + * @default null + */ + zone?: Zone, + + /** + * @default -1 + */ + zoneExpire?: number; + } + class Config implements ConfigOptions { + constructor(options?: ConfigOptions); + } + + class Zone { + srcUpHosts: any; + cdnUpHosts: any; + ioHost: string; + rsHost: string; + rsfHost: string; + apiHost: string; + + constructor(srcUpHosts?: any, cdnUpHosts?: any, ioHost?: string, rsHost?: string, rsfHost?: string, apiHost?: string); + } +} + +export declare namespace form_up { + class FormUploader { + conf: conf.Config; + + constructor(config?: conf.Config); + + /** + * + * @param uploadToken + * @param key + * @param rsStream + * @param putExtra + * @param callback + */ + putStream(uploadToken: string, key: string | null, rsStream: NodeJS.ReadableStream, putExtra: PutExtra | null, callback: callback): void; + + /** + * + * @param uploadToken + * @param key + * @param body + * @param putExtra + * @param callback + */ + put(uploadToken: string, key: string | null, body: any, putExtra: PutExtra | null, callback: callback): void; + + /** + * + * @param uploadToken + * @param body + * @param putExtra + * @param callback + */ + putWithoutKey(uploadToken: string, body: any, putExtra: PutExtra | null, callback: callback): void; + + /** + * 上传本地文件 + * @param uploadToken 上传凭证 + * @param key 目标文件名 + * @param localFile 本地文件路径 + * @param putExtra 额外选项 + * @param callback + */ + putFile(uploadToken: string, key: string | null, localFile: string, putExtra: PutExtra | null, callback: callback): void; + + /** + * + * @param uploadToken + * @param localFile + * @param putExtra + * @param callback + */ + putFileWithoutKey(uploadToken: string, localFile: string, putExtra: PutExtra | null, callback: callback): void; + } + + class PutExtra { + /** + * @default '' + */ + fname: string; + + /** + * @default {} + */ + params: any; + + /** + * @default null + */ + mimeType?: string; + + /** + * @default null + */ + crc32?: string; + + /** + * @default 0|false + */ + checkCrc?: number | boolean; + + /** + * 上传可选参数 + * @param fname 请求体中的文件的名称 + * @param params 额外参数设置,参数名称必须以x:开头 + * @param mimeType 指定文件的mimeType + * @param crc32 指定文件的crc32值 + * @param checkCrc 指定是否检测文件的crc32值 + */ + constructor(fname?: string, params?: any, mimeType?: string, crc32?: string, checkCrc?: number | boolean); + } +} + +export declare namespace resume_up { + class ResumeUploader { + config: conf.Config; + + constructor(config?: conf.Config); + + /** + * + * @param uploadToken + * @param key + * @param rsStream + * @param rsStreamLen + * @param putExtra + * @param callback + */ + putStream(uploadToken: string, key: string | null, rsStream: NodeJS.ReadableStream, rsStreamLen: number, putExtra: PutExtra | null, callback: callback): void; + + /** + * + * @param uploadToken + * @param key + * @param localFile + * @param putExtra + * @param callback + */ + putFile(uploadToken: string, key: string | null, localFile: string, putExtra: PutExtra | null, callback: callback): void; + + /** + * + * @param uploadToken + * @param localFile + * @param putExtra + * @param callback + */ + putFileWithoutKey(uploadToken: string, localFile: string, putExtra: PutExtra | null, callback: callback): void; + } + + class PutExtra { + /** + * @default '' + */ + fname: string; + + /** + * @default {} + */ + params: any; + + /** + * @default null + */ + mimeType?: string; + + /** + * 上传可选参数 + * @param fname 请求体中的文件的名称 + * @param params 额外参数设置,参数名称必须以x:开头 + * @param mimeType 指定文件的mimeType + * @param resumeRecordFile + * @param progressCallback + */ + constructor(fname?: string, params?: any, mimeType?: string, resumeRecordFile?: string, progressCallback?: (data: any) => void); + } +} + +export declare namespace util { + function isTimestampExpired(timestamp: number): boolean; + + function encodedEntry(bucket: string, key?: string): string; + + function getAKFromUptoken(uploadToken: string): string; + + function getBucketFromUptoken(uploadToken: string): string; + + function base64ToUrlSafe(v: string): string; + + function urlSafeToBase64(v: string): string; + + function urlsafeBase64Encode(jsonFlags: string): string; + + function urlSafeBase64Decode(fromStr: string): string; + + function hmacSha1(encodedFlags: string | Buffer, secretKey: string | Buffer): string; + + /** + * 创建AccessToken凭证 + * @param mac AK&SK对象 + * @param requestURI 请求URL + * @param reqBody 请求Body,仅当请求的ContentType为application/x-www-form-urlencoded 时才需要传入该参数 + */ + function generateAccessToken(mac: auth.digest.Mac, requestURI: string, reqBody?: string): string; + + + /** + * 创建AccessToken凭证 + * @param mac AK&SK对象 + * @param requestURI 请求URL + * @param reqMethod 请求方法,例如 GET,POST + * @param reqContentType 请求类型,例如 application/json 或者 application/x-www-form-urlencoded + * @param reqBody 请求Body,仅当请求的 ContentType 为 application/json 或者 application/x-www-form-urlencoded 时才需要传入该参数 + */ + function generateAccessTokenV2(mac: auth.digest.Mac, requestURI: string, reqMethod: string, reqContentType: string, reqBody?: string): string; + + /** + * 校验七牛上传回调的Authorization + * @param mac AK&SK对象 + * @param requestURI 回调的URL中的requestURI + * @param reqBody 回调的URL中的requestURI 请求Body,仅当请求的ContentType为application/x-www-form-urlencoded时才需要传入该参数 + * @param callbackAuth 回调时请求的Authorization头部值 + */ + function isQiniuCallback(mac: auth.digest.Mac, requestURI: string, reqBody: string | null, callbackAuth: string): boolean; +} + +export declare namespace rpc { + interface Headers { + 'User-Agent'?: string; + Connection?: string; + } + /** + * + * @param requestURI + * @param requestForm + * @param headers + * @param callback + */ + function post(requestURI: string, requestForm: Buffer | string | NodeJS.ReadableStream | null, headers: Headers | null, callback: callback): void; + + /** + * + * @param requestURI + * @param requestForm + * @param callback + */ + function postMultipart(requestURI: string, requestForm: Buffer | string | NodeJS.ReadableStream | null, callback: callback): void; + + /** + * + * @param requestURI + * @param requestForm + * @param token + * @param callback + */ + function postWithForm(requestURI: string, requestForm: Buffer | string | NodeJS.ReadableStream | null, token: string | null, callback: callback): void; + + /** + * + * @param requestURI + * @param token + * @param callback + */ + function postWithoutForm(requestURI: string, token: string | null, callback: callback): void; +} + +export declare namespace zone { + //huadong + const Zone_z0: conf.Zone; + //huabei + const Zone_z1: conf.Zone; + //huanan + const Zone_z2: conf.Zone; + //beimei + const Zone_na0: conf.Zone; + //Southeast Asia + const Zone_as0: conf.Zone; +} + +export declare namespace fop { + interface PfopOptions { + /** + * 回调业务服务器,通知处理结果 + */ + notifyURL?: string; + + /** + * 结果是否强制覆盖已有的同名文件 + */ + force?: boolean; + } + class OperationManager { + mac: auth.digest.Mac; + config: conf.Config; + + constructor(mac?: auth.digest.Mac, config?: conf.Config); + + /** + * 发送持久化数据处理请求 + * @param bucket 空间名称 + * @param key 文件名称 + * @param fops 处理指令集合 + * @param pipeline 处理队列名称 + * @param options + * @param callback + */ + pfop(bucket: string, key: string, fops: string[], pipeline: string, options: PfopOptions | null, callback: callback): void; + + /** + * 查询持久化数据处理进度 + * @param persistentId pfop操作返回的持久化处理ID + * @param callback + */ + prefop(persistentId: string, callback: callback): void; + } +} + +export declare namespace rs { + interface ListPrefixOptions { + /** + * 列举的文件前缀 + */ + prefix?: string; + + /** + * 上一次列举返回的位置标记 + */ + marker?: any; + + /** + * 每次返回的最大列举文件数量 + */ + limit?: number; + + /** + * 指定目录分隔符 + */ + delimiter?: string; + } + + class BucketManager { + mac: auth.digest.Mac; + config: conf.Config; + + constructor(mac?: auth.digest.Mac, config?: conf.Config); + + /** + * 获取资源信息 + * @see https://developer.qiniu.com/kodo/api/1308/stat + * + * @param bucket 空间名称 + * @param key 文件名称 + * @param callback + */ + stat(bucket: string, key: string, callback: callback): void; + + /** + * 修改文件的类型 + * @see https://developer.qiniu.com/kodo/api/1252/chgm + * + * @param bucket 空间名称 + * @param key 文件名称 + * @param newMime 新文件类型 + * @param callback + */ + changeMime(bucket: string, key: string, newMime: string, callback: callback): void; + + /** + * 修改文件的Headers + * @see TODO + * + * @param bucket 空间名称 + * @param key 文件名称 + * @param headers Headers对象 + * @param callback + */ + changeHeaders(bucket: string, key: string, headers: { [k: string]: string }, callback: callback): void; + + /** + * 移动或重命名文件,当bucketSrc==bucketDest相同的时候,就是重命名文件操作 + * @see https://developer.qiniu.com/kodo/api/1288/move + * + * @param srcBucket 源空间名称 + * @param srcKey 源文件名称 + * @param destBucket 目标空间名称 + * @param destKey 目标文件名称 + * @param options + * @param callback + */ + move(srcBucket: string, srcKey: string, destBucket: string, destKey: string, options: { force?: boolean } | null, callback: callback): void; + + /** + * 复制文件 + * @see https://developer.qiniu.com/kodo/api/1254/copy + * + * @param srcBucket 源空间名称 + * @param srcKey 源文件名称 + * @param destBucket 目标空间名称 + * @param destKey 目标文件名称 + * @param options + * @param callback + */ + copy(srcBucket: string, srcKey: string, destBucket: string, destKey: string, options: { force?: boolean } | null, callback: callback): void; + + /** + * 删除资源 + * @see https://developer.qiniu.com/kodo/api/1257/delete + * + * @param bucket 空间名称 + * @param key 文件名称 + * @param callback + */ + delete(bucket: string, key: string, callback: callback): void; + + /** + * 更新文件的生命周期 + * @see https://developer.qiniu.com/kodo/api/1732/update-file-lifecycle + * + * @param bucket 空间名称 + * @param key 文件名称 + * @param days 有效期天数 + * @param callback + */ + deleteAfterDays(bucket: string, key: string, days: number, callback: callback): void; + + /** + * 抓取资源 + * @see https://developer.qiniu.com/kodo/api/1263/fetch + * + * @param resUrl 资源链接 + * @param bucket 空间名称 + * @param key 文件名称 + * @param callback + */ + fetch(resUrl: string, bucket: string, key: string, callback: callback): void; + + /** + * 更新镜像副本 + * @see https://developer.qiniu.com/kodo/api/1293/prefetch + * + * @param bucket 空间名称 + * @param key 文件名称 + * @param callback + */ + prefetch(bucket: string, key: string, callback: callback): void; + + /** + * 修改文件的存储类型 + * @see https://developer.qiniu.com/kodo/api/3710/modify-the-file-type + * + * @param bucket 空间名称 + * @param key 文件名称 + * @param newType 0 表示标准存储;1 表示低频存储。 + * @param callback + */ + changeType(bucket: string, key: string, newType: number, callback: callback): void; + + /** + * 设置空间镜像源 + * @see https://developer.qiniu.com/kodo/api/1370/mirror + * + * @param bucket 空间名称 + * @param srcSiteUrl 镜像源地址 + * @param srcHost 镜像Host + * @param callback + */ + image(bucket: string, srcSiteUrl: string, srcHost: string, callback: callback): void; + + /** + * 取消设置空间镜像源 + * @see https://developer.qiniu.com/kodo/api/1370/mirror + * + * @param bucket 空间名称 + * @param callback + */ + unimage(bucket: string, callback: callback): void; + + /** + * 获取指定前缀的文件列表 + * @see https://developer.qiniu.com/kodo/api/1284/list + * + * @param bucket 空间名称 + * @param options 列举操作的可选参数 + * @param callback + */ + listPrefix(bucket: string, options: ListPrefixOptions | null, callback: callback): void; + + /** + * 批量文件管理请求,支持stat,chgm,chtype,delete,copy,move + * @param operations + * @param callback + */ + batch(operations: any, callback: callback): void; + + /** + * 获取私有空间的下载链接 + * @param domain 空间绑定的域名,比如以http或https开头 + * @param fileName 原始文件名 + * @param deadline 文件有效期时间戳(单位秒) + */ + privateDownloadUrl(domain: string, fileName: string, deadline: number): string; + + /** + * 获取公开空间的下载链接 + * @param domain 空间绑定的域名,比如以http或https开头 + * @param fileName 原始文件名 + */ + publicDownloadUrl(domain: string, fileName: string): string; + } + + /** + * + * @param bucket + * @param key + */ + function statOp(bucket: string, key: string): string; + + /** + * + * @param bucket + * @param key + */ + function deleteOp(bucket: string, key: string): string; + + /** + * + * @param bucket + * @param key + * @param days + */ + function deleteAfterDaysOp(bucket: string, key: string, days: number): string; + + /** + * + * @param bucket + * @param key + * @param newMime + */ + function changeMimeOp(bucket: string, key: string, newMime: string): string; + + /** + * + * @param bucket + * @param key + * @param headers + */ + function changeHeadersOp(bucket: string, key: string, headers: { [k: string]: string }): string; + + /** + * + * @param bucket + * @param key + * @param newType + */ + function changeTypeOp(bucket: string, key: string, newType: number): string; + + /** + * + * @param srcBucket + * @param srcKey + * @param destBucket + * @param destKey + * @param options + */ + function moveOp(srcBucket: string, srcKey: string, destBucket: string, destKey: string, options?: { force?: boolean }): string; + + /** + * + * @param srcBucket + * @param srcKey + * @param destBucket + * @param destKey + * @param options + */ + function copyOp(srcBucket: string, srcKey: string, destBucket: string, destKey: string, options?: { force?: boolean }): string; + + interface PutPolicyOptions { + scope?: string; + isPrefixalScope?: number; + expires?: number; + insertOnly?: number; + saveKey?: string; + endUser?: string; + returnUrl?: string; + returnBody?: string; + callbackUrl?: string; + callbackHost?: string; + callbackBody?: string; + callbackBodyType?: string; + callbackFetchKey?: number; + + persistentOps?: string; + persistentNotifyUrl?: string; + persistentPipeline?: string; + + fsizeLimit?: number; + fsizeMin?: number; + mimeLimit?: string; + + detectMime?: number; + deleteAfterDays?: number; + fileType?: number; + } + class PutPolicy { + constructor(options?: PutPolicyOptions); + + getFlags(): any; + + uploadToken(mac?: auth.digest.Mac): string; + } +} diff --git a/index.js b/index.js index db6efa33..7eec671e 100644 --- a/index.js +++ b/index.js @@ -1,16 +1,17 @@ -var libPath = process.env.QINIU_COV ? './lib-cov' : './qiniu'; - module.exports = { - auth: { - digest: require(libPath + '/auth' + '/digest.js') - }, - cdn: require(libPath + "/cdn.js"), - form_up: require(libPath + '/storage/form.js'), - resume_up: require(libPath + '/storage/resume.js'), - rs: require(libPath + '/storage/rs.js'), - fop: require(libPath + '/fop.js'), - conf: require(libPath + '/conf.js'), - rpc: require(libPath + '/rpc.js'), - util: require(libPath + '/util.js'), - zone: require(libPath + '/zone.js') + auth: { + digest: require('./qiniu/auth/digest.js') + }, + cdn: require('./qiniu/cdn.js'), + form_up: require('./qiniu/storage/form.js'), + resume_up: require('./qiniu/storage/resume.js'), + rs: require('./qiniu/storage/rs.js'), + fop: require('./qiniu/fop.js'), + conf: require('./qiniu/conf.js'), + rpc: require('./qiniu/rpc.js'), + util: require('./qiniu/util.js'), + zone: require('./qiniu/zone.js'), + app: require('./qiniu/rtc/app.js'), + room: require('./qiniu/rtc/room.js'), + Credentials: require('./qiniu/rtc/credentials.js') }; diff --git a/package.json b/package.json index 19957512..69c647b8 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,16 @@ { "name": "qiniu", - "version": "7.0.2", + "version": "7.2.2", "description": "Node wrapper for Qiniu Resource (Cloud) Storage API", "main": "index.js", "directories": { "test": "test" }, "scripts": { - "test": "make test", - "blanket": { - "pattern": "qiniu/qiniu", - "data-cover-flags": { - "debug": false - } - }, - "travis-cov": { - "threshold": 90 - } + "test": "NODE_ENV=test mocha -t 25000", + "cover": "nyc npm run test", + "report": "nyc report --reporter=html", + "lint": "eslint ." }, "repository": { "type": "git", @@ -33,36 +27,49 @@ "web-service" ], "author": "sdk@qiniu.com", - "contributors": [{ - "name": "Xu Shiwei", - "email": "xushiweizh@gmail.com" - }, { - "name": "why404", - "email": "awhy.xu@gmail.com" - }, { - "name": "ikbear", - "email": "sunikbear@gmail.com" - }, { - "name": "lintianzhi", - "email": "lintianzhi1992@gmail.com" - }], + "contributors": [ + { + "name": "Xu Shiwei", + "email": "xushiweizh@gmail.com" + }, + { + "name": "why404", + "email": "awhy.xu@gmail.com" + }, + { + "name": "guhao", + "email": "guhao@qiniu.com" + }, + { + "name": "jinxinxin", + "email": "jinxinxin@qiniu.com" + } + ], "engines": [ - "node >= 0.4.7" + "node >= 6" ], "dependencies": { - "mime": "1.3.6", - "formstream": "1.1.0", - "crc32": "0.2.2", - "urllib": "2.22.0", - "agentkeepalive": "3.3.0", - "urlencode": "1.1.0" + "agentkeepalive": "^4.0.2", + "block-stream2": "^2.0.0", + "crc32": "^0.2.2", + "destroy": "^1.0.4", + "encodeurl": "^1.0.1", + "formstream": "^1.1.0", + "mime": "^2.4.4", + "tunnel-agent": "^0.6.0", + "urllib": "^2.34.1" }, "devDependencies": { - "should": "1.2.2", - "pedding": "*", - "mocha": "*", - "blanket": "*", - "travis-cov": "*" + "@types/node": "^8.0.3", + "eslint": "^6.5.1", + "eslint-config-standard": "^14.1.0", + "eslint-plugin-import": "^2.11.0", + "eslint-plugin-node": "^10.0.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1", + "mocha": "^6.2.1", + "nyc": "^14.1.1", + "should": "^13.2.3" }, "license": "MIT" } diff --git a/qiniu/auth/digest.js b/qiniu/auth/digest.js index 669aadd0..973ba4ea 100644 --- a/qiniu/auth/digest.js +++ b/qiniu/auth/digest.js @@ -1,10 +1,8 @@ -var url = require('url'); var conf = require('../conf'); -var util = require('../util'); exports.Mac = Mac; -function Mac(accessKey, secretKey) { - this.accessKey = accessKey || conf.ACCESS_KEY; - this.secretKey = secretKey || conf.SECRET_KEY; +function Mac (accessKey, secretKey) { + this.accessKey = accessKey || conf.ACCESS_KEY; + this.secretKey = secretKey || conf.SECRET_KEY; } diff --git a/qiniu/cdn.js b/qiniu/cdn.js index 7e9a3891..75a4ce9b 100644 --- a/qiniu/cdn.js +++ b/qiniu/cdn.js @@ -3,12 +3,12 @@ const crypto = require('crypto'); const urllib = require('urllib'); const util = require('./util'); const digest = require('./auth/digest.js'); -const urlencode = require('urlencode'); +const encodeUrl = require('encodeurl'); exports.CdnManager = CdnManager; -function CdnManager(mac) { - this.mac = mac || new digest.Mac(); +function CdnManager (mac) { + this.mac = mac || new digest.Mac(); } // 获取域名日志下载链接 @@ -17,21 +17,13 @@ function CdnManager(mac) { // @param domains 域名列表 domains = ['obbid7qc6.qnssl.com','7xkh68.com1.z0.glb.clouddn.com'] // @param logDay 日期,例如 2016-07-01 // @param callbackFunc(err, respBody, respInfo) -CdnManager.prototype.getCdnLogList = function(domains, logDay, callbackFunc) { - var url = '/v2/tune/log/list\n'; - var accessToken = util.generateAccessToken(this.mac, url, ''); - var headers = { - 'Content-Type': 'application/json', - 'Authorization': accessToken, - }; - postBody = { - 'day': logDay, - 'domains': domains.join(';') - } - - req('/v2/tune/log/list', headers, postBody, callbackFunc); -} - +CdnManager.prototype.getCdnLogList = function (domains, logDay, callbackFunc) { + var postBody = { + day: logDay, + domains: domains.join(';') + }; + req(this.mac, '/v2/tune/log/list', postBody, callbackFunc); +}; // 获取域名访问流量数据 // @link http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html#batch-flux @@ -41,25 +33,17 @@ CdnManager.prototype.getCdnLogList = function(domains, logDay, callbackFunc) { // @param granularity 粒度,取值:5min/hour/day // @param domains 域名列表 domain = ['obbid7qc6.qnssl.com','obbid7qc6.qnssl.com']; // @param callbackFunc(err, respBody, respInfo) -CdnManager.prototype.getFluxData = function(startDate, endDate, granularity, - domains, - callbackFunc) { - var url = '/v2/tune/flux\n'; - var accessToken = util.generateAccessToken(this.mac, url, ''); - var headers = { - 'Content-Type': 'application/json', - 'Authorization': accessToken, - }; - data = { - 'startDate': startDate, - 'endDate': endDate, - 'granularity': granularity, - 'domains': domains.join(';') - } - - req('/v2/tune/flux', headers, data, callbackFunc); -} - +CdnManager.prototype.getFluxData = function (startDate, endDate, granularity, + domains, + callbackFunc) { + var data = { + startDate: startDate, + endDate: endDate, + granularity: granularity, + domains: domains.join(';') + }; + req(this.mac, '/v2/tune/flux', data, callbackFunc); +}; // 获取域名访问带宽数据 // @link http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html @@ -68,86 +52,67 @@ CdnManager.prototype.getFluxData = function(startDate, endDate, granularity, // @param granularity 粒度,取值:5min/hour/day // @param domains 域名列表 domain = ['obbid7qc6.qnssl.com','obbid7qc6.qnssl.com'] // @param callbackFunc(err, respBody, respInfo) -CdnManager.prototype.getBandwidthData = function(startDate, endDate, - granularity, domains, - callbackFunc) { - var url = '/v2/tune/bandwidth\n'; - var accessToken = util.generateAccessToken(this.mac, url, ''); - var headers = { - 'Content-Type': 'application/json', - 'Authorization': accessToken, - }; - data = { - 'startDate': startDate, - 'endDate': endDate, - 'granularity': granularity, - 'domains': domains.join(';') - } - - req('/v2/tune/bandwidth', headers, data, callbackFunc); -} - +CdnManager.prototype.getBandwidthData = function (startDate, endDate, + granularity, domains, + callbackFunc) { + var data = { + startDate: startDate, + endDate: endDate, + granularity: granularity, + domains: domains.join(';') + }; + req(this.mac, '/v2/tune/bandwidth', data, callbackFunc); +}; // 预取文件链接 // @link http://developer.qiniu.com/article/fusion/api/prefetch.html // // @param 预取urls urls = ['http://obbid7qc6.qnssl.com/023','http://obbid7qc6.qnssl.com/025'] // @param callbackFunc(err, respBody, respInfo) -CdnManager.prototype.prefetchUrls = function(urls, callbackFunc) { - var postBody = { - urls: urls - }; - var url = '/v2/tune/prefetch\n'; - var accessToken = util.generateAccessToken(this.mac, url, ''); - var headers = { - 'Content-Type': 'application/json', - 'Authorization': accessToken, - }; - - req('/v2/tune/prefetch', headers, postBody, callbackFunc); -} - +CdnManager.prototype.prefetchUrls = function (urls, callbackFunc) { + var postBody = { + urls: urls + }; + req(this.mac, '/v2/tune/prefetch', postBody, callbackFunc); +}; // 刷新链接 // @link http://developer.qiniu.com/article/fusion/api/refresh.html // 刷新urls refreshUrls = ['http://obbid7qc6.qnssl.com/023','http://obbid7qc6.qnssl.com/025'] -CdnManager.prototype.refreshUrls = function(urls, callbackFunc) { - this.refreshUrlsAndDirs(urls, null, callbackFunc); -} - +CdnManager.prototype.refreshUrls = function (urls, callbackFunc) { + this.refreshUrlsAndDirs(urls, null, callbackFunc); +}; // 刷新目录 // 刷新目录列表,每次最多不可以超过10个目录, 刷新目录需要额外开通权限,可以联系七牛技术支持处理 // @link http://developer.qiniu.com/article/fusion/api/refresh.html // 刷新dirs refreshDirs = ['http://obbid7qc6.qnssl.com/wo/','http://obbid7qc6.qnssl.com/'] -CdnManager.prototype.refreshDirs = function(dirs, callbackFunc) { - this.refreshUrlsAndDirs(null, dirs, callbackFunc); -} - - -CdnManager.prototype.refreshUrlsAndDirs = function(urls, dirs, callbackFunc) { - var postBody = { - urls: urls, - dirs: dirs, - }; - var url = '/v2/tune/refresh\n'; - var accessToken = util.generateAccessToken(this.mac, url, ''); - var headers = { - 'Content-Type': 'application/json', - 'Authorization': accessToken, - }; - - req('/v2/tune/refresh', headers, postBody, callbackFunc); -} - +CdnManager.prototype.refreshDirs = function (dirs, callbackFunc) { + this.refreshUrlsAndDirs(null, dirs, callbackFunc); +}; + +CdnManager.prototype.refreshUrlsAndDirs = function (urls, dirs, callbackFunc) { + var postBody = { + urls: urls, + dirs: dirs + }; + req(this.mac, '/v2/tune/refresh', postBody, callbackFunc); +}; // post 请求 -function req(reqPath, header, reqBody, callbackFunc) { - urllib.request("http://fusion.qiniuapi.com" + reqPath, { - method: 'POST', - headers: header, - data: reqBody, - }, callbackFunc); +function req (mac, reqPath, reqBody, callbackFunc) { + var url = 'http://fusion.qiniuapi.com' + reqPath; + var accessToken = util.generateAccessToken(mac, url, ''); + var headers = { + 'Content-Type': 'application/json', + Authorization: accessToken + }; + urllib.request(url, { + method: 'POST', + headers: headers, + data: reqBody, + dataType: 'json' + }, callbackFunc); } // 构建标准的基于时间戳的防盗链 @@ -158,30 +123,27 @@ function req(reqPath, header, reqBody, callbackFunc) { // @param encryptKey 时间戳防盗链的签名密钥,从七牛后台获取 // @param deadline 链接的有效期时间戳,是以秒为单位的Unix时间戳 // @return signedUrl 最终的带时间戳防盗链的url -CdnManager.prototype.createTimestampAntiLeechUrl = function(domain, fileName, - query, encryptKey, deadline) { - if (query != null) { - var arr = []; - Object.getOwnPropertyNames(query).forEach(function(val, idx, array) { - arr.push(val + "=" + urlencode(query[val])); - }); - urlToSign = domain + '/' + urlencode(fileName) + '?' + arr.join('&'); - } else { - urlToSign = domain + '/' + urlencode(fileName); - } - - var urlObj = url.parse(urlToSign); - pathname = urlObj.pathname; - - var expireHex = deadline.toString(16); - var signedStr = encryptKey + pathname + expireHex; - - var md5 = crypto.createHash('md5'); - var toSignStr = md5.update(signedStr).digest('hex'); - - if (query != null) { - return urlToSign + '&sign=' + toSignStr + '&t=' + expireHex; - } else { - return urlToSign + '?sign=' + toSignStr + '&t=' + expireHex; - } -} +CdnManager.prototype.createTimestampAntiLeechUrl = function (domain, fileName, + query, encryptKey, deadline) { + var urlToSign; + if (query != null) { + urlToSign = domain + '/' + encodeUrl(fileName) + '?' + query; + } else { + urlToSign = domain + '/' + encodeUrl(fileName); + } + + var urlObj = new url.URL(urlToSign); + var pathname = urlObj.pathname; + + var expireHex = deadline.toString(16); + var signedStr = encryptKey + pathname + expireHex; + + var md5 = crypto.createHash('md5'); + var toSignStr = md5.update(signedStr).digest('hex'); + + if (query != null) { + return urlToSign + '&sign=' + toSignStr + '&t=' + expireHex; + } else { + return urlToSign + '?sign=' + toSignStr + '&t=' + expireHex; + } +}; diff --git a/qiniu/conf.js b/qiniu/conf.js index c3642c0a..142dd244 100644 --- a/qiniu/conf.js +++ b/qiniu/conf.js @@ -1,74 +1,82 @@ -const fs = require('fs'); -const path = require('path'); const os = require('os'); const pkg = require('../package.json'); exports.ACCESS_KEY = ''; exports.SECRET_KEY = ''; -var defaultUserAgent = function() { - return 'QiniuNodejs/' + pkg.version + ' (' + os.type() + '; ' + os.platform() + +var defaultUserAgent = function () { + return 'QiniuNodejs/' + pkg.version + ' (' + os.type() + '; ' + os.platform() + '; ' + os.arch() + '; )'; -} +}; exports.USER_AGENT = defaultUserAgent(); -exports.BLOCK_SIZE = 4 * 1024 * 1024; //4MB, never change +exports.BLOCK_SIZE = 4 * 1024 * 1024; // 4MB, never change -//define api form mime type -exports.FormMimeUrl = "application/x-www-form-urlencoded"; -exports.FormMimeJson = "application/json"; -exports.FormMimeRaw = "application/octet-stream"; -exports.RS_HOST = "http://rs.qiniu.com"; -exports.RPC_TIMEOUT = 60000; //60s +// define api form mime type +exports.FormMimeUrl = 'application/x-www-form-urlencoded'; +exports.FormMimeJson = 'application/json'; +exports.FormMimeRaw = 'application/octet-stream'; +exports.RS_HOST = 'http://rs.qiniu.com'; +exports.RPC_TIMEOUT = 120000; // 120s +exports.UC_HOST = 'uc.qbox.me'; -exports.Config = function Config(options) { - options = options || {}; - //use http or https protocol - this.useHttpsDomain = options.useHttpsDomain || false; - //use cdn accerlated domains - this.useCdnDomain = options.useCdnDomain || true; - //zone of the bucket - //z0 huadong, z1 huabei, z2 huanan, na0 beimei - this.zone = options.zone || null; - this.zoneExpire = options.zoneExpire || -1; -} +// proxy +exports.RPC_HTTP_AGENT = null; +exports.RPC_HTTPS_AGENT = null; -exports.Zone = function(srcUpHosts, cdnUpHosts, ioHost, rsHost, rsfHost, - apiHost) { - this.srcUpHosts = srcUpHosts || {}; - this.cdnUpHosts = cdnUpHosts || {}; - this.ioHost = ioHost || ""; - this.rsHost = rsHost || "rs.qiniu.com"; - this.rsfHost = rsfHost || "rsf.qiniu.com"; - this.apiHost = apiHost || "api.qiniu.com"; - var dotIndex = this.ioHost.indexOf("."); - if (dotIndex != -1) { - var ioTag = this.ioHost.substring(0, dotIndex); - var zoneSepIndex = ioTag.indexOf("-"); - if (zoneSepIndex != -1) { - var zoneTag = ioTag.substring(zoneSepIndex + 1); - switch (zoneTag) { - case "z1": - this.rsHost = "rs-z1.qiniu.com"; - this.rsfHost = "rsf-z1.qiniu.com"; - this.apiHost = "api-z1.qiniu.com"; - break; - case "z2": - this.rsHost = "rs-z2.qiniu.com"; - this.rsfHost = "rsf-z2.qiniu.com"; - this.apiHost = "api-z2.qiniu.com"; - break; - case "na0": - this.rsHost = "rs-na0.qiniu.com"; - this.rsfHost = "rsf-na0.qiniu.com"; - this.apiHost = "api-na0.qiniu.com"; - break; - default: - this.rsHost = "rs.qiniu.com"; - this.rsfHost = "rsf.qiniu.com"; - this.apiHost = "api.qiniu.com"; - break; - } +exports.Config = function Config (options) { + options = options || {}; + // use http or https protocol + this.useHttpsDomain = !!(options.useHttpsDomain || false); + // use cdn accerlated domains + this.useCdnDomain = !!(options.useCdnDomain && true); + // zone of the bucket + // z0 huadong, z1 huabei, z2 huanan, na0 beimei + this.zone = options.zone || null; + this.zoneExpire = options.zoneExpire || -1; +}; + +exports.Zone = function (srcUpHosts, cdnUpHosts, ioHost, rsHost, rsfHost, + apiHost) { + this.srcUpHosts = srcUpHosts || {}; + this.cdnUpHosts = cdnUpHosts || {}; + this.ioHost = ioHost || ''; + this.rsHost = rsHost || 'rs.qiniu.com'; + this.rsfHost = rsfHost || 'rsf.qiniu.com'; + this.apiHost = apiHost || 'api.qiniu.com'; + var dotIndex = this.ioHost.indexOf('.'); + if (dotIndex != -1) { + var ioTag = this.ioHost.substring(0, dotIndex); + var zoneSepIndex = ioTag.indexOf('-'); + if (zoneSepIndex != -1) { + var zoneTag = ioTag.substring(zoneSepIndex + 1); + switch (zoneTag) { + case 'z1': + this.rsHost = 'rs-z1.qiniu.com'; + this.rsfHost = 'rsf-z1.qiniu.com'; + this.apiHost = 'api-z1.qiniu.com'; + break; + case 'z2': + this.rsHost = 'rs-z2.qiniu.com'; + this.rsfHost = 'rsf-z2.qiniu.com'; + this.apiHost = 'api-z2.qiniu.com'; + break; + case 'na0': + this.rsHost = 'rs-na0.qiniu.com'; + this.rsfHost = 'rsf-na0.qiniu.com'; + this.apiHost = 'api-na0.qiniu.com'; + break; + case 'as0': + this.rsHost = 'rs-as0.qiniu.com'; + this.rsfHost = 'rsf-as0.qiniu.com'; + this.apiHost = 'api-as0.qiniu.com'; + break; + default: + this.rsHost = 'rs.qiniu.com'; + this.rsfHost = 'rsf.qiniu.com'; + this.apiHost = 'api.qiniu.com'; + break; + } + } } - } -} +}; diff --git a/qiniu/fop.js b/qiniu/fop.js index 09374777..0ce52026 100644 --- a/qiniu/fop.js +++ b/qiniu/fop.js @@ -2,14 +2,13 @@ const util = require('./util'); const rpc = require('./rpc'); const conf = require('./conf'); const digest = require('./auth/digest'); -const zone = require('./zone.js'); const querystring = require('querystring'); exports.OperationManager = OperationManager; -function OperationManager(mac, config) { - this.mac = mac || new digest.Mac(); - this.config = config || new conf.Config(); +function OperationManager (mac, config) { + this.mac = mac || new digest.Mac(); + this.config = config || new conf.Config(); } // 发送持久化数据处理请求 @@ -21,97 +20,58 @@ function OperationManager(mac, config) { // notifyURL 回调业务服务器,通知处理结果 // force 结果是否强制覆盖已有的同名文件 // @param callbackFunc(err, respBody, respInfo) - 回调函数 -OperationManager.prototype.pfop = function(bucket, key, fops, pipeline, - options, callbackFunc) { - options = options || {}; - var that = this; - //必须参数 - var reqParams = { - bucket: bucket, - key: key, - pipeline: pipeline, - fops: fops.join(";"), - }; +OperationManager.prototype.pfop = function (bucket, key, fops, pipeline, + options, callbackFunc) { + options = options || {}; + // 必须参数 + var reqParams = { + bucket: bucket, + key: key, + pipeline: pipeline, + fops: fops.join(';') + }; - //notifyURL - if (options.notifyURL) { - reqParams.notifyURL = options.notifyURL; - } - - //force - if (options.force) { - reqParams.force = 1; - } - - var useCache = false; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } + // notifyURL + if (options.notifyURL) { + reqParams.notifyURL = options.notifyURL; } - } - if (useCache) { - pfopReq(this.mac, this.config, reqParams, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } + // force + if (options.force) { + reqParams.force = 1; + } - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //pfopReq - pfopReq(that.mac, that.config, reqParams, callbackFunc); + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + pfopReq(ctx.mac, ctx.config, reqParams, callbackFunc); }); - } -} +}; -function pfopReq(mac, config, reqParams, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var requestURI = scheme + config.zone.apiHost + '/pfop/'; - var reqBody = querystring.stringify(reqParams); - var auth = util.generateAccessToken(mac, requestURI, reqBody); - rpc.postWithForm(requestURI, reqBody, auth, callbackFunc); +function pfopReq (mac, config, reqParams, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + config.zone.apiHost + '/pfop/'; + var reqBody = querystring.stringify(reqParams); + var auth = util.generateAccessToken(mac, requestURI, reqBody); + rpc.postWithForm(requestURI, reqBody, auth, callbackFunc); } // 查询持久化数据处理进度 // @param persistentId // @callbackFunc(err, respBody, respInfo) - 回调函数 -OperationManager.prototype.prefop = function(persistentId, callbackFunc) { - var apiHost = "http://api.qiniu.com"; - var zoneIndex = persistentId.indexOf("."); - if (zoneIndex == -1) { - callbackFunc("invalid persistentId", null, null); - return; - } - var zoneTag = persistentId.substring(0, zoneIndex); - switch (zoneTag) { - case "z1": - apiHost = "api-z1.qiniu.com"; - break; - case "z2": - apiHost = "api-z2.qiniu.com"; - break; - case "na0": - apiHost = "api-na0.qiniu.com"; - break; - default: - apiHost = "api.qiniu.com"; - break; - } +OperationManager.prototype.prefop = function (persistentId, callbackFunc) { + var apiHost = 'api.qiniu.com'; + if (this.config.zone) { + apiHost = this.config.zone.apiHost; + } - var scheme = this.config.useHttpsDomain ? "https://" : "http://"; - var requestURI = scheme + apiHost + "/status/get/prefop"; - var reqParams = { - id: persistentId - }; - var reqBody = querystring.stringify(reqParams); - rpc.postWithForm(requestURI, reqBody, null, callbackFunc); -} + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + apiHost + '/status/get/prefop'; + var reqParams = { + id: persistentId + }; + var reqBody = querystring.stringify(reqParams); + rpc.postWithForm(requestURI, reqBody, null, callbackFunc); +}; diff --git a/qiniu/rpc.js b/qiniu/rpc.js index 76c6578c..8c52d58e 100644 --- a/qiniu/rpc.js +++ b/qiniu/rpc.js @@ -1,5 +1,4 @@ var urllib = require('urllib'); -var util = require('./util'); var conf = require('./conf'); exports.post = post; @@ -7,56 +6,64 @@ exports.postMultipart = postMultipart; exports.postWithForm = postWithForm; exports.postWithoutForm = postWithoutForm; -function postMultipart(requestURI, requestForm, callbackFunc) { - return post(requestURI, requestForm, requestForm.headers(), callbackFunc); +function postMultipart (requestURI, requestForm, callbackFunc) { + return post(requestURI, requestForm, requestForm.headers(), callbackFunc); } -function postWithForm(requestURI, requestForm, token, callbackFunc) { - var headers = { - 'Content-Type': 'application/x-www-form-urlencoded' - }; - if (token) { - headers['Authorization'] = token; - } - return post(requestURI, requestForm, headers, callbackFunc); +function postWithForm (requestURI, requestForm, token, callbackFunc) { + var headers = { + 'Content-Type': 'application/x-www-form-urlencoded' + }; + if (token) { + headers.Authorization = token; + } + return post(requestURI, requestForm, headers, callbackFunc); } -function postWithoutForm(requestURI, token, callbackFunc) { - var headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - }; - if (token) { - headers['Authorization'] = token; - } - return post(requestURI, null, headers, callbackFunc); +function postWithoutForm (requestURI, token, callbackFunc) { + var headers = { + 'Content-Type': 'application/x-www-form-urlencoded' + }; + if (token) { + headers.Authorization = token; + } + return post(requestURI, null, headers, callbackFunc); } -function post(requestURI, requestForm, headers, callbackFunc) { - //var start = parseInt(Date.now() / 1000); - headers = headers || {}; - headers['User-Agent'] = headers['User-Agent'] || conf.USER_AGENT; - headers['Connection'] = 'keep-alive'; +function post (requestURI, requestForm, headers, callbackFunc) { + // var start = parseInt(Date.now() / 1000); + headers = headers || {}; + headers['User-Agent'] = headers['User-Agent'] || conf.USER_AGENT; + headers.Connection = 'keep-alive'; - var data = { - headers: headers, - method: 'POST', - dataType: 'json', - timeout: conf.RPC_TIMEOUT, - gzip: true, + var data = { + headers: headers, + method: 'POST', + dataType: 'json', + timeout: conf.RPC_TIMEOUT, + gzip: true // timing: true, - }; + }; - if (Buffer.isBuffer(requestForm) || typeof requestForm === 'string') { - data.content = requestForm; - } else if (requestForm) { - data.stream = requestForm; - } else { - data.headers['Content-Length'] = 0; - }; + if (conf.RPC_HTTP_AGENT) { + data.agent = conf.RPC_HTTP_AGENT; + } - var req = urllib.request(requestURI, data, function(respErr, respBody, - respInfo) { - //var end = parseInt(Date.now() / 1000); + if (conf.RPC_HTTPS_AGENT) { + data.httpsAgent = conf.RPC_HTTPS_AGENT; + } + + if (Buffer.isBuffer(requestForm) || typeof requestForm === 'string') { + data.content = requestForm; + } else if (requestForm) { + data.stream = requestForm; + } else { + data.headers['Content-Length'] = 0; + } + + var req = urllib.request(requestURI, data, function (respErr, respBody, + respInfo) { + // var end = parseInt(Date.now() / 1000); // console.log((end - start) + " seconds"); // console.log("queuing:\t" + respInfo.timing.queuing); // console.log("dnslookup:\t" + respInfo.timing.dnslookup); @@ -65,8 +72,8 @@ function post(requestURI, requestForm, headers, callbackFunc) { // console.log("waiting:\t" + respInfo.timing.waiting); // console.log("contentDownload:\t" + respInfo.timing.contentDownload); - callbackFunc(respErr, respBody, respInfo); - }); + callbackFunc(respErr, respBody, respInfo); + }); - return req; + return req; } diff --git a/qiniu/rtc/app.js b/qiniu/rtc/app.js new file mode 100644 index 00000000..e8b8ebe7 --- /dev/null +++ b/qiniu/rtc/app.js @@ -0,0 +1,121 @@ +var http = require('http'); + +const host = 'rtc.qiniuapi.com'; +const headers = { + 'Content-Type': 'application/json' +}; + +function get (credentials, options, fn) { + options.headers.Authorization = credentials.generateAccessToken(options, null); + + var req = http.request(options, function (res) { + res.setEncoding('utf-8'); + + var responseString = ''; + + res.on('data', function (data) { + responseString += data; + }); + + res.on('end', function () { + var resultObject = JSON.parse(responseString); + + if (res.statusCode != 200) { + var result = { + code: res.statusCode, + message: res.statusMessage + }; + fn(result, null); + } else { + fn(null, resultObject); + } + }); + }); + + req.on('error', function (e) { + fn(e, null); + }); + + req.end(); +} + +function post (credentials, options, data, fn) { + var dataString = JSON.stringify(data); + + options.headers.Authorization = credentials.generateAccessToken(options, dataString); + + var req = http.request(options, function (res) { + res.setEncoding('utf-8'); + + var responseString = ''; + + res.on('data', function (data) { + responseString += data; + }); + + res.on('end', function () { + var resultObject = JSON.parse(responseString); + + if (res.statusCode != 200) { + var result = { + code: res.statusCode, + message: res.statusMessage + }; + fn(result, null); + } else { + fn(null, resultObject); + } + }); + }); + req.on('error', function (e) { + fn(e, null); + }); + + req.write(dataString); + + req.end(); +} + +exports.createApp = function (app, credentials, fn) { + var options = { + host: host, + port: 80, + path: '/v3/apps', + method: 'POST', + headers: headers + }; + post(credentials, options, app, fn); +}; + +exports.getApp = function (appId, credentials, fn) { + var options = { + host: host, + port: 80, + path: '/v3/apps/' + appId, + method: 'GET', + headers: headers + }; + get(credentials, options, fn); +}; + +exports.deleteApp = function (appId, credentials, fn) { + var options = { + host: host, + port: 80, + path: '/v3/apps/' + appId, + method: 'DELETE', + headers: headers + }; + get(credentials, options, fn); +}; + +exports.updateApp = function (appId, app, credentials, fn) { + var options = { + host: host, + port: 80, + path: '/v3/apps/' + appId, + method: 'POST', + headers: headers + }; + post(credentials, options, app, fn); +}; diff --git a/qiniu/rtc/credentials.js b/qiniu/rtc/credentials.js new file mode 100644 index 00000000..9b9c12b8 --- /dev/null +++ b/qiniu/rtc/credentials.js @@ -0,0 +1,57 @@ +var util = require('./util'); + +function Credentials (accessKey, secretKey) { + this.accessKey = accessKey; + this.secretKey = secretKey; +} + +Credentials.prototype.generateAccessToken = function (options, data) { + var sign = this._signRequest(options, data); + var token = 'Qiniu' + ' ' + this.accessKey + ':' + sign; + + return token; +}; + +Credentials.prototype._signRequest = function (options, body) { + var contentType = options.headers['Content-Type']; + + var host = options.host; + if (options.port && options.port != 80) { + host = host + ':' + options.port; + } + + var data = options.method + ' ' + options.path; + data += '\nHost: ' + host; + if (contentType) { + data += '\nContent-Type: ' + contentType; + } + data += '\n\n'; + + if (body && contentType && contentType != 'application/octet-stream') { + data += body; + } + + var digest = util.hmacSha1(data, this.secretKey); + + var sageDigest = util.base64ToUrlSafe(digest); + + return sageDigest; +}; + +Credentials.prototype.sign = function (data) { + var digest = util.hmacSha1(data, this.secretKey); + var sageDigest = util.base64ToUrlSafe(digest); + return this.accessKey + ':' + sageDigest; +}; + +Credentials.prototype.signJson = function (opt) { + var str = JSON.stringify(opt); + var encodedStr = util.urlsafeBase64Encode(str); + var sign = util.hmacSha1(encodedStr, this.secretKey); + var encodedSign = util.base64ToUrlSafe(sign); + + var token = this.accessKey + ':' + encodedSign + ':' + encodedStr; + return token; +}; + +module.exports = exports = Credentials; diff --git a/qiniu/rtc/room.js b/qiniu/rtc/room.js new file mode 100644 index 00000000..dc6a8999 --- /dev/null +++ b/qiniu/rtc/room.js @@ -0,0 +1,118 @@ +var http = require('http'); + +const host = 'rtc.qiniuapi.com'; +const headers = { + 'Content-Type': 'application/json' +}; + +function get (credentials, options, fn) { + options.headers.Authorization = credentials.generateAccessToken(options, null); + + var req = http.request(options, function (res) { + res.setEncoding('utf-8'); + + var responseString = ''; + + res.on('data', function (data) { + responseString += data; + }); + + res.on('end', function () { + // var resultObject = JSON.parse(responseString); + // console.log(JSON.parse(responseString)) + + if (res.statusCode != 200) { + var result = { + code: res.statusCode, + message: res.statusMessage + }; + fn(result, null); + } else { + fn(null, JSON.parse(responseString)); + } + }); + }); + + req.on('error', function (e) { + fn(e, null); + }); + + req.end(); +} + +// function post(credentials, options, data, fn) { +// var dataString = JSON.stringify(data); + +// options.headers['Authorization'] = credentials.generateAccessToken(options, dataString); + +// var req = http.request(options, function(res) { +// res.setEncoding('utf-8'); + +// var responseString = ''; + +// res.on('data', function(data) { +// responseString += data; +// }); + +// res.on('end', function() { +// var resultObject = JSON.parse(responseString); + +// if (res.statusCode != 200) { +// var result = { +// code: res.statusCode, +// message: res.statusMessage +// }; +// fn(result, null); +// } else { +// fn(null, resultObject); +// } +// }); +// }); +// req.on('error', function(e) { +// fn(e, null); +// }); + +// req.write(dataString); + +// req.end(); +// } + +exports.listUser = function (appId, roomName, credentials, fn) { + var options = { + host: host, + port: 80, + path: '/v3/apps/' + appId + '/rooms/' + roomName + '/users', + method: 'GET', + headers: headers + }; + get(credentials, options, fn); +}; + +exports.kickUser = function (appId, roomName, userId, credentials, fn) { + var options = { + host: host, + port: 80, + path: '/v3/apps/' + appId + '/rooms/' + roomName + '/users/' + userId, + method: 'DELETE', + headers: headers + }; + get(credentials, options, fn); +}; + +exports.listActiveRooms = function (appId, roomNamePrefix, offset, limit, credentials, fn) { + var options = { + host: host, + port: 80, + path: '/v3/apps/' + appId + '/rooms?prefix=' + roomNamePrefix + '&offset=' + offset + '&limit=' + limit, + method: 'GET', + headers: headers + }; + get(credentials, options, fn); +}; + +exports.getRoomToken = function (roomAccess, credentials) { + if (!roomAccess.expireAt) { + roomAccess.expireAt = Math.floor(Date.now() / 1000) + 3600; + } + return credentials.signJson(roomAccess); +}; diff --git a/qiniu/rtc/util.js b/qiniu/rtc/util.js new file mode 100644 index 00000000..dec4c362 --- /dev/null +++ b/qiniu/rtc/util.js @@ -0,0 +1,16 @@ +var crypto = require('crypto'); + +exports.base64ToUrlSafe = function (v) { + return v.replace(/\//g, '_').replace(/\+/g, '-'); +}; + +exports.urlsafeBase64Encode = function (jsonFlags) { + var encoded = Buffer.from(jsonFlags).toString('base64'); + return exports.base64ToUrlSafe(encoded); +}; + +exports.hmacSha1 = function (encodedFlags, secretKey) { + var hmac = crypto.createHmac('sha1', secretKey); + hmac.update(encodedFlags); + return hmac.digest('base64'); +}; diff --git a/qiniu/storage/form.js b/qiniu/storage/form.js index a49d1eb2..91d0f3c9 100644 --- a/qiniu/storage/form.js +++ b/qiniu/storage/form.js @@ -7,14 +7,12 @@ const path = require('path'); const mime = require('mime'); const Readable = require('stream').Readable; const formstream = require('formstream'); -const zone = require('../zone'); -const digest = require('../auth/digest'); exports.FormUploader = FormUploader; exports.PutExtra = PutExtra; -function FormUploader(config) { - this.config = config || new conf.Config(); +function FormUploader (config) { + this.config = config || new conf.Config(); } // 上传可选参数 @@ -23,171 +21,138 @@ function FormUploader(config) { // @param mimeType 指定文件的mimeType // @param crc32 指定文件的crc32值 // @param checkCrc 指定是否检测文件的crc32值 -function PutExtra(fname, params, mimeType, crc32, checkCrc) { - this.fname = fname || ''; - this.params = params || {}; - this.mimeType = mimeType || null; - this.crc32 = crc32 || null; - this.checkCrc = checkCrc || 0; +function PutExtra (fname, params, mimeType, crc32, checkCrc) { + this.fname = fname || ''; + this.params = params || {}; + this.mimeType = mimeType || null; + this.crc32 = crc32 || null; + this.checkCrc = checkCrc || 1; } -FormUploader.prototype.putStream = function(uploadToken, key, rsStream, - putExtra, callbackFunc) { - putExtra = putExtra || new PutExtra(); - if (!putExtra.mimeType) { - putExtra.mimeType = 'application/octet-stream'; - } - - if (!putExtra.fname) { - putExtra.fname = key ? key : '?'; - } - - rsStream.on("error", function(err) { - //callbackFunc - callbackFunc(err, null, null); - return; - }); - - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } +FormUploader.prototype.putStream = function (uploadToken, key, fsStream, + putExtra, callbackFunc) { + putExtra = putExtra || new PutExtra(); + if (!putExtra.mimeType) { + putExtra.mimeType = 'application/octet-stream'; } - } - - var accessKey = util.getAKFromUptoken(uploadToken); - var bucket = util.getBucketFromUptoken(uploadToken); - if (useCache) { - var postForm = createMultipartForm(uploadToken, key, rsStream, putExtra); - putReq(this.config, postForm, callbackFunc); - } else { - zone.getZoneInfo(accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; + if (!putExtra.fname) { + putExtra.fname = key || 'fname'; + } - //req - var postForm = createMultipartForm(uploadToken, key, rsStream, - putExtra); - putReq(that.config, postForm, callbackFunc); + fsStream.on('error', function (err) { + // callbackFunc + callbackFunc(err, null, null); }); - } -} - -function putReq(config, postForm, callbackFunc) { - //set up hosts order - var upHosts = []; - if (config.useCdnDomain) { - if (config.zone.cdnUpHosts) { - config.zone.cdnUpHosts.forEach(function(host) { - upHosts.push(host); - }); - } - config.zone.srcUpHosts.forEach(function(host) { - upHosts.push(host); + var accessKey = util.getAKFromUptoken(uploadToken); + var bucket = util.getBucketFromUptoken(uploadToken); + + util.prepareZone(this, accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + createMultipartForm(uploadToken, key, fsStream, putExtra, function (postForm) { + putReq(ctx.config, postForm, callbackFunc); + }); }); - } else { - config.zone.srcUpHosts.forEach(function(host) { - upHosts.push(host); - }); - config.zone.cdnUpHosts.forEach(function(host) { - upHosts.push(host); - }); - } +}; + +function putReq (config, postForm, callbackFunc) { + // set up hosts order + var upHosts = []; + + if (config.useCdnDomain) { + if (config.zone.cdnUpHosts) { + config.zone.cdnUpHosts.forEach(function (host) { + upHosts.push(host); + }); + } + config.zone.srcUpHosts.forEach(function (host) { + upHosts.push(host); + }); + } else { + config.zone.srcUpHosts.forEach(function (host) { + upHosts.push(host); + }); + config.zone.cdnUpHosts.forEach(function (host) { + upHosts.push(host); + }); + } - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var upDomain = scheme + upHosts[0]; - rpc.postMultipart(upDomain, postForm, callbackFunc); + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var upDomain = scheme + upHosts[0]; + rpc.postMultipart(upDomain, postForm, callbackFunc); } // 上传字节 // -FormUploader.prototype.put = function(uploadToken, key, body, putExtra, - callbackFunc) { - var rsStream = new Readable(); - rsStream.push(body); - rsStream.push(null); - - putExtra = putExtra || new PutExtra(); - - if (putExtra.checkCrc == 1) { - var bodyCrc32 = getCrc32(body); - putExtra.crc32 = '' + parsStreameInt(bodyCrc32, 16); - } else if (putExtra.checkCrc == 2 && putExtra.crc32) { - putExtra.crc32 = '' + putExtra.crc32 - } - return this.putStream(uploadToken, key, rsStream, putExtra, callbackFunc) -} - -FormUploader.prototype.putWithoutKey = function(uploadToken, body, putExtra, - callbackFunc) { - return this.put(uploadToken, null, body, putExtra, callbackFunc); -} +FormUploader.prototype.put = function (uploadToken, key, body, putExtra, + callbackFunc) { + var fsStream = new Readable(); + fsStream.push(body); + fsStream.push(null); + + putExtra = putExtra || new PutExtra(); + return this.putStream(uploadToken, key, fsStream, putExtra, callbackFunc); +}; + +FormUploader.prototype.putWithoutKey = function (uploadToken, body, putExtra, + callbackFunc) { + return this.put(uploadToken, null, body, putExtra, callbackFunc); +}; + +function createMultipartForm (uploadToken, key, fsStream, putExtra, callbackFunc) { + var postForm = formstream(); + postForm.field('token', uploadToken); + if (key) { + postForm.field('key', key); + } + postForm.stream('file', fsStream, putExtra.fname, putExtra.mimeType); -function createMultipartForm(uploadToken, key, rsStream, putExtra) { - var postForm = formstream(); - postForm.field('token', uploadToken); - if (key) { - postForm.field('key', key); - } - postForm.stream('file', rsStream, putExtra.fname, putExtra.mimeType); - if (putExtra.crc32) { - postForm.field('crc32', putExtra.crc32); - } - - //putExtra params - for (var k in putExtra.params) { - if (k.startsWith("x:")) { - postForm.field(k, putExtra.params[k].toString()); + // putExtra params + for (var k in putExtra.params) { + if (k.startsWith('x:')) { + postForm.field(k, putExtra.params[k].toString()); + } } - } + var fileBody = []; + fsStream.on('data', function (data) { + fileBody.push(data); + }); - return postForm; + fsStream.on('end', function () { + fileBody = Buffer.concat(fileBody); + var bodyCrc32 = parseInt('0x' + getCrc32(fileBody)); + postForm.field('crc32', bodyCrc32); + }); + callbackFunc(postForm); } - // 上传本地文件 // @params uploadToken 上传凭证 // @param key 目标文件名 // @param localFile 本地文件路径 // @param putExtra 额外选项 // @param callbackFunc 回调函数 -FormUploader.prototype.putFile = function(uploadToken, key, localFile, putExtra, - callbackFunc) { - putExtra = putExtra || new PutExtra(); - var rsStream = fs.createReadStream(localFile); - - if (putExtra.checkCrc == 1) { - var fileCrc32 = getCrc32(fs.readFileSync(localFile)); - putExtra.crc32 = '' + parsStreameInt(fileCrc32, 16); - } else if (putExtra.checkCrc == 2 && putExtra.crc32) { - putExtra.crc32 = '' + putExtra.crc32 - } - - if (!putExtra.mimeType) { - putExtra.mimeType = mime.lookup(localFile); - } - - if (!putExtra.fname) { - putExtra.fname = path.basename(localFile); - } - - return this.putStream(uploadToken, key, rsStream, putExtra, callbackFunc); -} +FormUploader.prototype.putFile = function (uploadToken, key, localFile, putExtra, + callbackFunc) { + putExtra = putExtra || new PutExtra(); + var fsStream = fs.createReadStream(localFile); -FormUploader.prototype.putFileWithoutKey = function(uploadToken, localFile, - putExtra, callbackFunc) { - return this.putFile(uploadToken, null, localFile, putExtra, callbackFunc); -} + if (!putExtra.mimeType) { + putExtra.mimeType = mime.getType(localFile); + } + + if (!putExtra.fname) { + putExtra.fname = path.basename(localFile); + } + + return this.putStream(uploadToken, key, fsStream, putExtra, callbackFunc); +}; + +FormUploader.prototype.putFileWithoutKey = function (uploadToken, localFile, + putExtra, callbackFunc) { + return this.putFile(uploadToken, null, localFile, putExtra, callbackFunc); +}; diff --git a/qiniu/storage/resume.js b/qiniu/storage/resume.js index 7c34d893..7af5478a 100644 --- a/qiniu/storage/resume.js +++ b/qiniu/storage/resume.js @@ -1,16 +1,18 @@ const conf = require('../conf'); -const zone = require('../zone'); const util = require('../util'); const rpc = require('../rpc'); const path = require('path'); const mime = require('mime'); const fs = require('fs'); +const getCrc32 = require('crc32'); +const destroy = require('destroy'); +const BlockStream = require('block-stream2'); exports.ResumeUploader = ResumeUploader; exports.PutExtra = PutExtra; -function ResumeUploader(config) { - this.config = config || new conf.Config(); +function ResumeUploader (config) { + this.config = config || new conf.Config(); } // 上传可选参数 @@ -18,246 +20,227 @@ function ResumeUploader(config) { // @params params 额外参数设置,参数名称必须以x:开头 // @param mimeType 指定文件的mimeType // @param resumeRecordFile 断点续传的已上传的部分信息记录文件 -// @param progressCallback(BlkputRet) 上传进度回调 -function PutExtra(fname, params, mimeType, resumeRecordFile, progressCallback) { - this.fname = fname || ''; - this.params = params || {}; - this.mimeType = mimeType || null; - this.resumeRecordFile = resumeRecordFile || null; - this.progressCallback = progressCallback || null; +// @param progressCallback(uploadBytes, totalBytes) 上传进度回调 +function PutExtra (fname, params, mimeType, resumeRecordFile, progressCallback) { + this.fname = fname || ''; + this.params = params || {}; + this.mimeType = mimeType || null; + this.resumeRecordFile = resumeRecordFile || null; + this.progressCallback = progressCallback || null; } -ResumeUploader.prototype.putStream = function(uploadToken, key, rsStream, - rsStreamLen, putExtra, callbackFunc) { - putExtra = putExtra || new PutExtra(); - if (!putExtra.mimeType) { - putExtra.mimeType = 'application/octet-stream'; - } - - if (!putExtra.fname) { - putExtra.fname = key ? key : '?'; - } - - rsStream.on("error", function(err) { - //callbackFunc - callbackFunc(err, null, null); - return; - }); +ResumeUploader.prototype.putStream = function (uploadToken, key, rsStream, + rsStreamLen, putExtra, callbackFunc) { + putExtra = putExtra || new PutExtra(); + if (!putExtra.mimeType) { + putExtra.mimeType = 'application/octet-stream'; + } - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } + if (!putExtra.fname) { + putExtra.fname = key || '?'; } - } - var accessKey = util.getAKFromUptoken(uploadToken); - var bucket = util.getBucketFromUptoken(uploadToken); - if (useCache) { - putReq(this.config, uploadToken, key, rsStream, rsStreamLen, putExtra, - callbackFunc); - } else { - zone.getZoneInfo(accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { + rsStream.on('error', function (err) { + // callbackFunc callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - - //req - putReq(that.config, uploadToken, key, rsStream, rsStreamLen, - putExtra, - callbackFunc); + destroy(rsStream); }); - } -} -function putReq(config, uploadToken, key, rsStream, rsStreamLen, putExtra, - callbackFunc) { - //set up hosts order - var upHosts = []; + var accessKey = util.getAKFromUptoken(uploadToken); + var bucket = util.getBucketFromUptoken(uploadToken); - if (config.useCdnDomain) { - if (config.zone.cdnUpHosts) { - config.zone.cdnUpHosts.forEach(function(host) { - upHosts.push(host); - }); - } - config.zone.srcUpHosts.forEach(function(host) { - upHosts.push(host); - }); - } else { - config.zone.srcUpHosts.forEach(function(host) { - upHosts.push(host); - }); - config.zone.cdnUpHosts.forEach(function(host) { - upHosts.push(host); + util.prepareZone(this, accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + destroy(rsStream); + return; + } + putReq(ctx.config, uploadToken, key, rsStream, rsStreamLen, putExtra, + callbackFunc); }); - } - - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var upDomain = scheme + upHosts[0]; - // block upload - - var fileSize = rsStreamLen; - //console.log("file size:" + fileSize); - var blockCnt = fileSize / conf.BLOCK_SIZE - var totalBlockNum = (fileSize % conf.BLOCK_SIZE == 0) ? blockCnt : (blockCnt + - 1); - var finishedBlock = 0; - var curBlock = 0; - var readLen = 0; - var readBuffers = []; - var finishedCtxList = []; - var finishedBlkPutRets = []; - //read resumeRecordFile - if (putExtra.resumeRecordFile) { - try { - var resumeRecords = fs.readFileSync(putExtra.resumeRecordFile).toString(); - var blkputRets = JSON.parse(resumeRecords); - - for (var index = 0; index < blkputRets.length; index++) { - //check ctx expired or not - var blkputRet = blkputRets[index]; - var expiredAt = blkputRet.expired_at; - //make sure the ctx at least has one day expiration - expiredAt += 3600 * 24; - if (util.isTimestampExpired(expiredAt)) { - //discard these ctxs - break; +}; + +function putReq (config, uploadToken, key, rsStream, rsStreamLen, putExtra, + callbackFunc) { + // set up hosts order + var upHosts = []; + + if (config.useCdnDomain) { + if (config.zone.cdnUpHosts) { + config.zone.cdnUpHosts.forEach(function (host) { + upHosts.push(host); + }); } + config.zone.srcUpHosts.forEach(function (host) { + upHosts.push(host); + }); + } else { + config.zone.srcUpHosts.forEach(function (host) { + upHosts.push(host); + }); + config.zone.cdnUpHosts.forEach(function (host) { + upHosts.push(host); + }); + } - finishedBlock += 1; - finishedCtxList.push(blkputRet.ctx); - } - } catch (e) {} - } - - //check when to mkblk - rsStream.on('data', function(chunk) { - readLen += chunk.length; - readBuffers.push(chunk); - - if (readLen % conf.BLOCK_SIZE == 0 || readLen == fileSize) { - //console.log(readLen); - var readData = Buffer.concat(readBuffers); - readBuffers = []; //reset read buffer - curBlock += 1; //set current block - if (curBlock > finishedBlock) { - rsStream.pause(); - mkblkReq(upDomain, uploadToken, readData, function(respErr, - respBody, - respInfo) { - if (respInfo.statusCode != 200) { - callbackFunc(respErr, respBody, respInfo); - return; - } else { - finishedBlock += 1; - rsStream.resume(); - var blkputRet = respBody; - finishedCtxList.push(blkputRet.ctx); - finishedBlkPutRets.push(blkputRet); - if (putExtra.progressCallback) { - putExtra.progressCallback(blkputRet); + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var upDomain = scheme + upHosts[0]; + // block upload + + var blkStream = rsStream.pipe(new BlockStream({ + size: conf.BLOCK_SIZE, + zeroPadding: false + })); + + var readLen = 0; + var curBlock = 0; + var finishedBlock = 0; + var finishedCtxList = []; + var finishedBlkPutRets = []; + var isSent = false; + var totalBlockNum = Math.ceil(rsStreamLen / conf.BLOCK_SIZE); + // read resumeRecordFile + if (putExtra.resumeRecordFile) { + try { + var resumeRecords = fs.readFileSync(putExtra.resumeRecordFile).toString(); + var blkputRets = JSON.parse(resumeRecords); + + for (var index = 0; index < blkputRets.length; index++) { + // check ctx expired or not + var blkputRet = blkputRets[index]; + var expiredAt = blkputRet.expired_at; + // make sure the ctx at least has one day expiration + expiredAt += 3600 * 24; + if (util.isTimestampExpired(expiredAt)) { + // discard these ctxs + break; + } + + finishedBlock += 1; + finishedCtxList.push(blkputRet.ctx); + finishedBlkPutRets.push(blkputRet); } - if (putExtra.resumeRecordFile) { - var contents = JSON.stringify(finishedBlkPutRets); - console.log("write resume record " + putExtra.resumeRecordFile) - fs.writeFileSync(putExtra.resumeRecordFile, contents, { - encoding: 'utf-8' - }); - } - } - }); - } + } catch (e) { + // log(e); + } } - }); - //check when to mkfile - rsStream.on('end', function() { - //console.log("end"); - mkfileReq(upDomain, uploadToken, fileSize, finishedCtxList, key, - putExtra, callbackFunc); - }); + // check when to mkblk + blkStream.on('data', function (chunk) { + readLen += chunk.length; + curBlock += 1; // set current block + if (curBlock > finishedBlock) { + blkStream.pause(); + mkblkReq(upDomain, uploadToken, chunk, function (respErr, + respBody, + respInfo) { + var bodyCrc32 = parseInt('0x' + getCrc32(chunk)); + if (respInfo.statusCode != 200 || respBody.crc32 != bodyCrc32) { + callbackFunc(respErr, respBody, respInfo); + destroy(rsStream); + } else { + finishedBlock += 1; + var blkputRet = respBody; + finishedCtxList.push(blkputRet.ctx); + finishedBlkPutRets.push(blkputRet); + if (putExtra.progressCallback) { + putExtra.progressCallback(readLen, rsStreamLen); + } + if (putExtra.resumeRecordFile) { + var contents = JSON.stringify(finishedBlkPutRets); + // console.log('write resume record ' + putExtra.resumeRecordFile); + fs.writeFileSync(putExtra.resumeRecordFile, contents, { + encoding: 'utf-8' + }); + } + blkStream.resume(); + if (finishedCtxList.length === totalBlockNum) { + mkfileReq(upDomain, uploadToken, rsStreamLen, finishedCtxList, key, putExtra, callbackFunc); + isSent = true; + } + } + }); + } + }); + + blkStream.on('end', function () { + if (!isSent && rsStreamLen === 0) { + mkfileReq(upDomain, uploadToken, rsStreamLen, finishedCtxList, key, putExtra, callbackFunc); + } + destroy(rsStream); + }); } -function mkblkReq(upDomain, uploadToken, blkData, callbackFunc) { - //console.log("mkblk"); - var requestURI = upDomain + "/mkblk/" + blkData.length; - var auth = 'UpToken ' + uploadToken; - var headers = { - 'Authorization': auth, - 'Content-Type': 'application/octet-stream' - } - rpc.post(requestURI, blkData, headers, callbackFunc); +function mkblkReq (upDomain, uploadToken, blkData, callbackFunc) { + // console.log("mkblk"); + var requestURI = upDomain + '/mkblk/' + blkData.length; + var auth = 'UpToken ' + uploadToken; + var headers = { + Authorization: auth, + 'Content-Type': 'application/octet-stream' + }; + rpc.post(requestURI, blkData, headers, callbackFunc); } -function mkfileReq(upDomain, uploadToken, fileSize, ctxList, key, putExtra, - callbackFunc) { - //console.log("mkfile"); - var requestURI = upDomain + "/mkfile/" + fileSize; - if (key) { - requestURI += "/key/" + util.urlsafeBase64Encode(key); - } - if (putExtra.mimeType) { - requestURI += "/mimeType/" + util.urlsafeBase64Encode(putExtra.mimeType); - } - if (putExtra.fname) { - requestURI += "/fname/" + util.urlsafeBase64Encode(putExtra.fname); - } - if (putExtra.params) { - //putExtra params - for (var k in putExtra.params) { - if (k.startsWith("x:") && putExtra.params[k]) { - requestURI += "/" + k + "/" + util.urlsafeBase64Encode(putExtra.params[ - k].toString()); - } +function mkfileReq (upDomain, uploadToken, fileSize, ctxList, key, putExtra, + callbackFunc) { + // console.log("mkfile"); + var requestURI = upDomain + '/mkfile/' + fileSize; + if (key) { + requestURI += '/key/' + util.urlsafeBase64Encode(key); } - } - var auth = 'UpToken ' + uploadToken; - var headers = { - 'Authorization': auth, - 'Content-Type': 'application/octet-stream' - } - var postBody = ctxList.join(","); - rpc.post(requestURI, postBody, headers, function(err, ret, info) { - if (info.statusCode == 200 || info.statusCode == 701 || - info.statusCode == 401) { - if (putExtra.resumeRecordFile) { - fs.unlinkSync(putExtra.resumeRecordFile); - } + if (putExtra.mimeType) { + requestURI += '/mimeType/' + util.urlsafeBase64Encode(putExtra.mimeType); + } + if (putExtra.fname) { + requestURI += '/fname/' + util.urlsafeBase64Encode(putExtra.fname); + } + if (putExtra.params) { + // putExtra params + for (var k in putExtra.params) { + if (k.startsWith('x:') && putExtra.params[k]) { + requestURI += '/' + k + '/' + util.urlsafeBase64Encode(putExtra.params[ + k].toString()); + } + } } - callbackFunc(err, ret, info); - }); + var auth = 'UpToken ' + uploadToken; + var headers = { + Authorization: auth, + 'Content-Type': 'application/octet-stream' + }; + var postBody = ctxList.join(','); + rpc.post(requestURI, postBody, headers, function (err, ret, info) { + if (info.statusCode == 200 || info.statusCode == 701 || + info.statusCode == 401) { + if (putExtra.resumeRecordFile) { + fs.unlinkSync(putExtra.resumeRecordFile); + } + } + callbackFunc(err, ret, info); + }); } -ResumeUploader.prototype.putFile = function(uploadToken, key, localFile, - putExtra, callbackFunc) { - putExtra = putExtra || new PutExtra(); - var rsStream = fs.createReadStream(localFile); - var rsStreamLen = fs.statSync(localFile).size; - if (!putExtra.mimeType) { - putExtra.mimeType = mime.lookup(localFile); - } +ResumeUploader.prototype.putFile = function (uploadToken, key, localFile, + putExtra, callbackFunc) { + putExtra = putExtra || new PutExtra(); + var rsStream = fs.createReadStream(localFile, { + highWaterMark: conf.BLOCK_SIZE + }); + var rsStreamLen = fs.statSync(localFile).size; + if (!putExtra.mimeType) { + putExtra.mimeType = mime.getType(localFile); + } - if (!putExtra.fname) { - putExtra.fname = path.basename(localFile); - } + if (!putExtra.fname) { + putExtra.fname = path.basename(localFile); + } - return this.putStream(uploadToken, key, rsStream, rsStreamLen, putExtra, - callbackFunc); -} + return this.putStream(uploadToken, key, rsStream, rsStreamLen, putExtra, + callbackFunc); +}; -ResumeUploader.prototype.putFileWithoutKey = function(uploadToken, localFile, - putExtra, callbackFunc) { - return this.putFile(uploadToken, null, localFile, putExtra, callbackFunc); -} +ResumeUploader.prototype.putFileWithoutKey = function (uploadToken, localFile, + putExtra, callbackFunc) { + return this.putFile(uploadToken, null, localFile, putExtra, callbackFunc); +}; diff --git a/qiniu/storage/rs.js b/qiniu/storage/rs.js index 50cc62bd..e212f5a2 100644 --- a/qiniu/storage/rs.js +++ b/qiniu/storage/rs.js @@ -1,19 +1,16 @@ -const url = require('url'); -const crypto = require('crypto'); -const formstream = require('formstream'); const querystring = require('querystring'); +const encodeUrl = require('encodeurl'); const rpc = require('../rpc'); const conf = require('../conf'); const digest = require('../auth/digest'); const util = require('../util'); -const zone = require('../zone'); exports.BucketManager = BucketManager; exports.PutPolicy = PutPolicy; -function BucketManager(mac, config) { - this.mac = mac || new digest.Mac(); - this.config = config || new conf.Config(); +function BucketManager (mac, config) { + this.mac = mac || new digest.Mac(); + this.config = config || new conf.Config(); } // 获取资源信息 @@ -21,44 +18,22 @@ function BucketManager(mac, config) { // @param bucket 空间名称 // @param key 文件名称 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.stat = function(bucket, key, callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - statReq(this.mac, this.config, bucket, key, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - statReq(that.mac, that.config, bucket, key, callbackFunc); +BucketManager.prototype.stat = function (bucket, key, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + statReq(ctx.mac, ctx.config, bucket, key, callbackFunc); }); - } -} - -function statReq(mac, config, bucket, key, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var statOp = exports.statOp(bucket, key); - var requestURI = scheme + config.zone.rsHost + statOp; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +function statReq (mac, config, bucket, key, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var statOp = exports.statOp(bucket, key); + var requestURI = scheme + config.zone.rsHost + statOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } // 修改文件的类型 @@ -67,46 +42,48 @@ function statReq(mac, config, bucket, key, callbackFunc) { // @param key 文件名称 // @param newMime 新文件类型 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.changeMime = function(bucket, key, newMime, - callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - changeMimeReq(this.mac, this.config, bucket, key, newMime, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - changeMimeReq(that.mac, that.config, bucket, key, newMime, - callbackFunc); +BucketManager.prototype.changeMime = function (bucket, key, newMime, + callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + changeMimeReq(ctx.mac, ctx.config, bucket, key, newMime, callbackFunc); }); - } +}; + +function changeMimeReq (mac, config, bucket, key, newMime, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var changeMimeOp = exports.changeMimeOp(bucket, key, newMime); + var requestURI = scheme + config.zone.rsHost + changeMimeOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } -function changeMimeReq(mac, config, bucket, key, newMime, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var changeMimeOp = exports.changeMimeOp(bucket, key, newMime); - var requestURI = scheme + config.zone.rsHost + changeMimeOp; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +// 修改文件返回的Headers内容 +// @link TODO +// @param bucket 空间名称 +// @param key 文件名称 +// @param headers 需要修改的headers +// @param callbackFunc(err, respBody, respInfo) 回调函数 +BucketManager.prototype.changeHeaders = function (bucket, key, headers, + callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + changeHeadersReq(ctx.mac, ctx.config, bucket, key, headers, callbackFunc); + }); +}; + +function changeHeadersReq (mac, config, bucket, key, headers, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var changeHeadersOp = exports.changeHeadersOp(bucket, key, headers); + var requestURI = scheme + config.zone.rsHost + changeHeadersOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } // 移动或重命名文件,当bucketSrc==bucketDest相同的时候,就是重命名文件操作 @@ -118,48 +95,25 @@ function changeMimeReq(mac, config, bucket, key, newMime, callbackFunc) { // @param options 可选参数 // force 强制覆盖 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.move = function(srcBucket, srcKey, destBucket, destKey, - options, callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - moveReq(this.mac, this.config, srcBucket, srcKey, destBucket, destKey, - options, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, srcBucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - moveReq(that.mac, that.config, srcBucket, srcKey, destBucket, - destKey, options, callbackFunc); +BucketManager.prototype.move = function (srcBucket, srcKey, destBucket, destKey, + options, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, srcBucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + moveReq(ctx.mac, ctx.config, srcBucket, srcKey, destBucket, destKey, + options, callbackFunc); }); - } -} - -function moveReq(mac, config, srcBucket, srcKey, destBucket, destKey, - options, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var moveOp = exports.moveOp(srcBucket, srcKey, destBucket, destKey, options); - var requestURI = scheme + config.zone.rsHost + moveOp; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +function moveReq (mac, config, srcBucket, srcKey, destBucket, destKey, + options, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var moveOp = exports.moveOp(srcBucket, srcKey, destBucket, destKey, options); + var requestURI = scheme + config.zone.rsHost + moveOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } // 复制一个文件 @@ -171,49 +125,26 @@ function moveReq(mac, config, srcBucket, srcKey, destBucket, destKey, // @param options 可选参数 // force 强制覆盖 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.copy = function(srcBucket, srcKey, destBucket, destKey, - options, callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - copyReq(this.mac, this.config, srcBucket, srcKey, destBucket, destKey, - options, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, srcBucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - copyReq(that.mac, that.config, srcBucket, srcKey, destBucket, - destKey, options, callbackFunc); +BucketManager.prototype.copy = function (srcBucket, srcKey, destBucket, destKey, + options, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, srcBucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + copyReq(ctx.mac, ctx.config, srcBucket, srcKey, destBucket, destKey, + options, callbackFunc); }); - } -} - -function copyReq(mac, config, srcBucket, srcKey, destBucket, destKey, - options, callbackFunc) { - options = options || {}; - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var copyOp = exports.copyOp(srcBucket, srcKey, destBucket, destKey, options); - var requestURI = scheme + config.zone.rsHost + copyOp; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +function copyReq (mac, config, srcBucket, srcKey, destBucket, destKey, + options, callbackFunc) { + options = options || {}; + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var copyOp = exports.copyOp(srcBucket, srcKey, destBucket, destKey, options); + var requestURI = scheme + config.zone.rsHost + copyOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } // 删除资源 @@ -221,93 +152,47 @@ function copyReq(mac, config, srcBucket, srcKey, destBucket, destKey, // @param bucket 空间名称 // @param key 文件名称 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.delete = function(bucket, key, callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - deleteReq(this.mac, this.config, bucket, key, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - deleteReq(that.mac, that.config, bucket, key, callbackFunc); +BucketManager.prototype.delete = function (bucket, key, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + deleteReq(ctx.mac, ctx.config, bucket, key, callbackFunc); }); - } +}; + +function deleteReq (mac, config, bucket, key, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var deleteOp = exports.deleteOp(bucket, key); + var requestURI = scheme + config.zone.rsHost + deleteOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } -function deleteReq(mac, config, bucket, key, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var deleteOp = exports.deleteOp(bucket, key); - var requestURI = scheme + config.zone.rsHost + deleteOp; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); -} - - // 更新文件的生命周期 // @link https://developer.qiniu.com/kodo/api/1732/update-file-lifecycle // @param bucket 空间名称 // @param key 文件名称 // @param days 有效期天数 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.deleteAfterDays = function(bucket, key, days, - callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - deleteAfterDaysReq(this.mac, this.config, bucket, key, days, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - deleteAfterDaysReq(that.mac, that.config, bucket, key, days, - callbackFunc); +BucketManager.prototype.deleteAfterDays = function (bucket, key, days, + callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + deleteAfterDaysReq(ctx.mac, ctx.config, bucket, key, days, callbackFunc); }); - } -} - -function deleteAfterDaysReq(mac, config, bucket, key, days, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var deleteAfterDaysOp = exports.deleteAfterDaysOp(bucket, key, days); - var requestURI = scheme + config.zone.rsHost + deleteAfterDaysOp; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +function deleteAfterDaysReq (mac, config, bucket, key, days, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var deleteAfterDaysOp = exports.deleteAfterDaysOp(bucket, key, days); + var requestURI = scheme + config.zone.rsHost + deleteAfterDaysOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } // 抓取资源 @@ -316,46 +201,24 @@ function deleteAfterDaysReq(mac, config, bucket, key, days, callbackFunc) { // @param bucket 空间名称 // @param key 文件名称 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.fetch = function(resUrl, bucket, key, callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - fetchReq(this.mac, this.config, resUrl, bucket, key, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - fetchReq(that.mac, that.config, resUrl, bucket, key, callbackFunc); +BucketManager.prototype.fetch = function (resUrl, bucket, key, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + fetchReq(ctx.mac, ctx.config, resUrl, bucket, key, callbackFunc); }); - } -} - -function fetchReq(mac, config, resUrl, bucket, key, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var encodedEntryURI = util.encodedEntry(bucket, key); - var encodedResURL = util.urlsafeBase64Encode(resUrl); - var requestURI = scheme + config.zone.ioHost + '/fetch/' + encodedResURL + - '/to/' + encodedEntryURI; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +function fetchReq (mac, config, resUrl, bucket, key, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var encodedEntryURI = util.encodedEntry(bucket, key); + var encodedResURL = util.urlsafeBase64Encode(resUrl); + var requestURI = scheme + config.zone.ioHost + '/fetch/' + encodedResURL + + '/to/' + encodedEntryURI; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } // 更新镜像副本 @@ -363,44 +226,22 @@ function fetchReq(mac, config, resUrl, bucket, key, callbackFunc) { // @param bucket 空间名称 // @param key 文件名称 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.prefetch = function(bucket, key, callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - prefetchReq(this.mac, this.config, bucket, key, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - prefetchReq(that.mac, that.config, bucket, key, callbackFunc); +BucketManager.prototype.prefetch = function (bucket, key, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + prefetchReq(ctx.mac, ctx.config, bucket, key, callbackFunc); }); - } -} - -function prefetchReq(mac, config, bucket, key, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var encodedEntryURI = util.encodedEntry(bucket, key); - var requestURI = scheme + config.zone.ioHost + '/prefetch/' + encodedEntryURI; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +function prefetchReq (mac, config, bucket, key, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var encodedEntryURI = util.encodedEntry(bucket, key); + var requestURI = scheme + config.zone.ioHost + '/prefetch/' + encodedEntryURI; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } // 修改文件的存储类型 @@ -409,77 +250,53 @@ function prefetchReq(mac, config, bucket, key, callbackFunc) { // @param key 文件名称 // @param newType 新文件存储类型 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.changeType = function(bucket, key, newType, - callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - changeTypeReq(this.mac, this.config, bucket, key, newType, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - changeTypeReq(that.mac, that.config, bucket, key, newType, - callbackFunc); +BucketManager.prototype.changeType = function (bucket, key, newType, + callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + changeTypeReq(ctx.mac, ctx.config, bucket, key, newType, callbackFunc); }); - } -} - -function changeTypeReq(mac, config, bucket, key, newType, callbackFunc) { - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var changeTypeOp = exports.changeTypeOp(bucket, key, newType); - var requestURI = scheme + config.zone.rsHost + changeTypeOp; - var digest = util.generateAccessToken(mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +function changeTypeReq (mac, config, bucket, key, newType, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var changeTypeOp = exports.changeTypeOp(bucket, key, newType); + var requestURI = scheme + config.zone.rsHost + changeTypeOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } - // 设置空间镜像源 // @link https://developer.qiniu.com/kodo/api/1370/mirror // @param bucket 空间名称 // @param srcSiteUrl 镜像源地址 // @param srcHost 镜像Host // @param callbackFunc(err, respBody, respInfo) 回调函数 -const PU_HOST = "http://pu.qbox.me:10200"; -BucketManager.prototype.image = function(bucket, srcSiteUrl, srcHost, - callbackFunc) { - var encodedSrcSite = util.urlsafeBase64Encode(srcSiteUrl); - var requestURI = PU_HOST + "/image/" + bucket + "/from/" + encodedSrcSite; - if (srcHost) { - var encodedHost = util.urlsafeBase64Encode(srcHost); - requestURI += "/host/" + encodedHost; - } - var digest = util.generateAccessToken(this.mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); -} +const PU_HOST = 'http://pu.qbox.me:10200'; +BucketManager.prototype.image = function (bucket, srcSiteUrl, srcHost, + callbackFunc) { + var encodedSrcSite = util.urlsafeBase64Encode(srcSiteUrl); + var requestURI = PU_HOST + '/image/' + bucket + '/from/' + encodedSrcSite; + if (srcHost) { + var encodedHost = util.urlsafeBase64Encode(srcHost); + requestURI += '/host/' + encodedHost; + } + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; // 取消设置空间镜像源 // @link https://developer.qiniu.com/kodo/api/1370/mirror // @param bucket 空间名称 // @param callbackFunc(err, respBody, respInfo) 回调函数 -BucketManager.prototype.unimage = function(bucket, callbackFunc) { - var requestURI = PU_HOST + "/unimage/" + bucket; - var digest = util.generateAccessToken(this.mac, requestURI, null); - rpc.postWithoutForm(requestURI, digest, callbackFunc); -} +BucketManager.prototype.unimage = function (bucket, callbackFunc) { + var requestURI = PU_HOST + '/unimage/' + bucket; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; // 获取指定前缀的文件列表 // @link https://developer.qiniu.com/kodo/api/1284/list @@ -491,135 +308,189 @@ BucketManager.prototype.unimage = function(bucket, callbackFunc) { // limit 每次返回的最大列举文件数量 // delimiter 指定目录分隔符 // @param callbackFunc(err, respBody, respInfo) - 回调函数 -BucketManager.prototype.listPrefix = function(bucket, options, callbackFunc) { - var useCache = false; - var that = this; - if (this.config.zone) { - if (this.config.zoneExpire == -1) { - useCache = true; - } else { - if (!util.isTimestampExpired(this.config.zoneExpire)) { - useCache = true; - } - } - } - - if (useCache) { - listPrefixReq(this.mac, this.config, bucket, options, callbackFunc); - } else { - zone.getZoneInfo(this.mac.accessKey, bucket, function(err, cZoneInfo, - cZoneExpire) { - if (err) { - callbackFunc(err, null, null); - return; - } - - //update object - that.config.zone = cZoneInfo; - that.config.zoneExpire = cZoneExpire; - //req - listPrefixReq(that.mac, that.config, bucket, options, callbackFunc); +BucketManager.prototype.listPrefix = function (bucket, options, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + listPrefixReq(ctx.mac, ctx.config, bucket, options, callbackFunc); }); - } -} +}; -function listPrefixReq(mac, config, bucket, options, callbackFunc) { - options = options || {}; - //必须参数 - var reqParams = { - bucket: bucket, - }; - - if (options.prefix) { - reqParams.prefix = options.prefix; - } else { - reqParams.prefix = ""; - } - - if (options.limit >= 1 && options.limit <= 1000) { - reqParams.limit = options.limit; - } else { - reqParams.limit = 1000; - } - - if (options.marker) { - reqParams.marker = options.marker; - } else { - reqParams.marker = ""; - } - - if (options.delimiter) { - reqParams.delimiter = options.delimiter; - } else { - reqParams.delimiter = ""; - } - - var scheme = config.useHttpsDomain ? "https://" : "http://"; - var reqSpec = querystring.stringify(reqParams); - var requestURI = scheme + config.zone.rsfHost + '/list?' + reqSpec; - - var auth = util.generateAccessToken(mac, requestURI, null); - rpc.postWithForm(requestURI, null, auth, callbackFunc); -} +function listPrefixReq (mac, config, bucket, options, callbackFunc) { + options = options || {}; + // 必须参数 + var reqParams = { + bucket: bucket + }; -// 批量文件管理请求,支持stat,chgm,chtype,delete,copy,move -BucketManager.prototype.batch = function(operations, callbackFunc) { - var requestURI = conf.RS_HOST + "/batch"; - var reqParams = { - op: operations, - }; - var reqBody = querystring.stringify(reqParams); - var digest = util.generateAccessToken(this.mac, requestURI, reqBody); - rpc.postWithForm(requestURI, reqBody, digest, callbackFunc); -} + if (options.prefix) { + reqParams.prefix = options.prefix; + } else { + reqParams.prefix = ''; + } -// 批量操作支持的指令构造器 -exports.statOp = function(bucket, key) { - return "/stat/" + util.encodedEntry(bucket, key); -} + if (options.limit >= 1 && options.limit <= 1000) { + reqParams.limit = options.limit; + } else { + reqParams.limit = 1000; + } -exports.deleteOp = function(bucket, key) { - return "/delete/" + util.encodedEntry(bucket, key); -} + if (options.marker) { + reqParams.marker = options.marker; + } else { + reqParams.marker = ''; + } -exports.deleteAfterDaysOp = function(bucket, key, days) { - var encodedEntryURI = util.encodedEntry(bucket, key); - return '/deleteAfterDays/' + encodedEntryURI + "/" + days; -} + if (options.delimiter) { + reqParams.delimiter = options.delimiter; + } else { + reqParams.delimiter = ''; + } -exports.changeMimeOp = function(bucket, key, newMime) { - var encodedEntryURI = util.encodedEntry(bucket, key); - var encodedMime = util.urlsafeBase64Encode(newMime); - return '/chgm/' + encodedEntryURI + '/mime/' + encodedMime; -} + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + config.zone.rsfHost + '/list?' + reqSpec; -exports.changeTypeOp = function(bucket, key, newType) { - var encodedEntryURI = util.encodedEntry(bucket, key); - return '/chtype/' + encodedEntryURI + '/type/' + newType; + var auth = util.generateAccessToken(mac, requestURI, null); + rpc.postWithForm(requestURI, null, auth, callbackFunc); } -exports.moveOp = function(srcBucket, srcKey, destBucket, destKey, options) { - options = options || {}; - var encodedEntryURISrc = util.encodedEntry(srcBucket, srcKey); - var encodedEntryURIDest = util.encodedEntry(destBucket, destKey); - var op = "/move/" + encodedEntryURISrc + "/" + encodedEntryURIDest; - if (options.force) { - op += "/force/true"; - } - return op; -} +// 获取指定前缀的文件列表 +// +// @param bucket 空间名称 +// @param options 列举操作的可选参数 +// prefix 列举的文件前缀 +// marker 上一次列举返回的位置标记,作为本次列举的起点信息 +// limit 每次返回的最大列举文件数量 +// delimiter 指定目录分隔符 +// @param callbackFunc(err, respBody, respInfo) - 回调函数 +BucketManager.prototype.listPrefixV2 = function (bucket, options, callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + listPrefixReqV2(ctx.mac, ctx.config, bucket, options, callbackFunc); + }); +}; + +function listPrefixReqV2 (mac, config, bucket, options, callbackFunc) { + options = options || {}; + // 必须参数 + var reqParams = { + bucket: bucket + }; + + if (options.prefix) { + reqParams.prefix = options.prefix; + } else { + reqParams.prefix = ''; + } + + if (options.limit) { + reqParams.limit = Math.min(1000, Math.max(0, options.limit)); + } else { + reqParams.limit = 0; + } + + if (options.marker) { + reqParams.marker = options.marker; + } else { + reqParams.marker = ''; + } + + if (options.delimiter) { + reqParams.delimiter = options.delimiter; + } else { + reqParams.delimiter = ''; + } + + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + config.zone.rsfHost + '/v2/list?' + reqSpec; -exports.copyOp = function(srcBucket, srcKey, destBucket, destKey, options) { - options = options || {}; - var encodedEntryURISrc = util.encodedEntry(srcBucket, srcKey); - var encodedEntryURIDest = util.encodedEntry(destBucket, destKey); - var op = "/copy/" + encodedEntryURISrc + "/" + encodedEntryURIDest; - if (options.force) { - op += "/force/true"; - } - return op; + var auth = util.generateAccessToken(mac, requestURI, null); + rpc.postWithForm(requestURI, null, auth, callbackFunc); } +// 批量文件管理请求,支持stat,chgm,chtype,delete,copy,move +BucketManager.prototype.batch = function (operations, callbackFunc) { + var requestURI = conf.RS_HOST + '/batch'; + var reqParams = { + op: operations + }; + var reqBody = querystring.stringify(reqParams); + var digest = util.generateAccessToken(this.mac, requestURI, reqBody); + rpc.postWithForm(requestURI, reqBody, digest, callbackFunc); +}; + +// 批量操作支持的指令构造器 +exports.statOp = function (bucket, key) { + return '/stat/' + util.encodedEntry(bucket, key); +}; + +exports.deleteOp = function (bucket, key) { + return '/delete/' + util.encodedEntry(bucket, key); +}; + +exports.deleteAfterDaysOp = function (bucket, key, days) { + var encodedEntryURI = util.encodedEntry(bucket, key); + return '/deleteAfterDays/' + encodedEntryURI + '/' + days; +}; + +exports.changeMimeOp = function (bucket, key, newMime) { + var encodedEntryURI = util.encodedEntry(bucket, key); + var encodedMime = util.urlsafeBase64Encode(newMime); + return '/chgm/' + encodedEntryURI + '/mime/' + encodedMime; +}; + +exports.changeHeadersOp = function (bucket, key, headers) { + var encodedEntryURI = util.encodedEntry(bucket, key); + var prefix = 'x-qn-meta-!'; + var path = '/chgm/' + encodedEntryURI; + for (var headerKey in headers) { + var encodedValue = util.urlsafeBase64Encode(headers[headerKey]); + var prefixedHeaderKey = prefix + headerKey; + path += '/' + prefixedHeaderKey + '/' + encodedValue; + } + + return path; +}; + +exports.changeTypeOp = function (bucket, key, newType) { + var encodedEntryURI = util.encodedEntry(bucket, key); + return '/chtype/' + encodedEntryURI + '/type/' + newType; +}; + +exports.changeStatusOp = function (bucket, key, newStatus) { + var encodedEntryURI = util.encodedEntry(bucket, key); + return '/chstatus/' + encodedEntryURI + '/status/' + newStatus; +}; + +exports.moveOp = function (srcBucket, srcKey, destBucket, destKey, options) { + options = options || {}; + var encodedEntryURISrc = util.encodedEntry(srcBucket, srcKey); + var encodedEntryURIDest = util.encodedEntry(destBucket, destKey); + var op = '/move/' + encodedEntryURISrc + '/' + encodedEntryURIDest; + if (options.force) { + op += '/force/true'; + } + return op; +}; + +exports.copyOp = function (srcBucket, srcKey, destBucket, destKey, options) { + options = options || {}; + var encodedEntryURISrc = util.encodedEntry(srcBucket, srcKey); + var encodedEntryURIDest = util.encodedEntry(destBucket, destKey); + var op = '/copy/' + encodedEntryURISrc + '/' + encodedEntryURIDest; + if (options.force) { + op += '/force/true'; + } + return op; +}; + // 空间资源下载 // 获取私有空间的下载链接 @@ -627,95 +498,544 @@ exports.copyOp = function(srcBucket, srcKey, destBucket, destKey, options) { // @param fileName 原始文件名 // @param deadline 文件有效期时间戳(单位秒) // @return 私有下载链接 -BucketManager.prototype.privateDownloadUrl = function(domain, fileName, - deadline) { - var baseUrl = this.publicDownloadUrl(domain, fileName); - if (baseUrl.indexOf('?') >= 0) { - baseUrl += '&e='; - } else { - baseUrl += '?e='; - } - baseUrl += deadline; - - var signature = util.hmacSha1(baseUrl, this.mac.secretKey); - var encodedSign = util.base64ToUrlSafe(signature); - var downloadToken = this.mac.accessKey + ':' + encodedSign; - return baseUrl + '&token=' + downloadToken; -} +BucketManager.prototype.privateDownloadUrl = function (domain, fileName, + deadline) { + var baseUrl = this.publicDownloadUrl(domain, fileName); + if (baseUrl.indexOf('?') >= 0) { + baseUrl += '&e='; + } else { + baseUrl += '?e='; + } + baseUrl += deadline; + + var signature = util.hmacSha1(baseUrl, this.mac.secretKey); + var encodedSign = util.base64ToUrlSafe(signature); + var downloadToken = this.mac.accessKey + ':' + encodedSign; + return baseUrl + '&token=' + downloadToken; +}; // 获取公开空间的下载链接 // @param domain 空间绑定的域名,比如以http或https开头 // @param fileName 原始文件名 // @return 公开下载链接 -BucketManager.prototype.publicDownloadUrl = function(domain, fileName) { - return domain + "/" + encodeURI(fileName); +BucketManager.prototype.publicDownloadUrl = function (domain, fileName) { + return domain + '/' + encodeUrl(fileName); +}; +// 修改文件状态 +// @link https://developer.qiniu.com/kodo/api/4173/modify-the-file-status +// @param bucket 空间名称 +// @param key 文件名称 +// @param status 文件状态 +// @param callbackFunc(err, respBody, respInfo) 回调函数 +// updateObjectStatus(bucketName string, key string, status ObjectStatus, condition UpdateObjectInfoCondition) +BucketManager.prototype.updateObjectStatus = function (bucket, key, status, + callbackFunc) { + util.prepareZone(this, this.mac.accessKey, bucket, function (err, ctx) { + if (err) { + callbackFunc(err, null, null); + return; + } + updateStatusReq(ctx.mac, ctx.config, bucket, key, status, callbackFunc); + }); +}; + +function updateStatusReq (mac, config, bucket, key, status, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var changeStatusOp = exports.changeStatusOp(bucket, key, status); + var requestURI = scheme + config.zone.rsHost + changeStatusOp; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } -// 上传策略 -// @link https://developer.qiniu.com/kodo/manual/1206/put-policy -function PutPolicy(options) { - if (typeof options !== 'object') { - throw new Error('invalid putpolicy options'); - } - - this.scope = options.scope || null; - this.isPrefixalScope = options.isPrefixalScope || null; - this.expires = options.expires || 3600; - this.insertOnly = options.insertOnly || null; - - this.saveKey = options.saveKey || null; - this.endUser = options.endUser || null; - - this.returnUrl = options.returnUrl || null; - this.returnBody = options.returnBody || null; - - this.callbackUrl = options.callbackUrl || null; - this.callbackHost = options.callbackHost || null; - this.callbackBody = options.callbackBody || null; - this.callbackBodyType = options.callbackBodyType || null; - this.callbackFetchKey = options.callbackFetchKey || null; - - this.persistentOps = options.persistentOps || null; - this.persistentNotifyUrl = options.persistentNotifyUrl || null; - this.persistentPipeline = options.persistentPipeline || null; - - this.fsizeLimit = options.fsizeLimit || null; - this.fsizeMin = options.fsizeMin || null; - this.mimeLimit = options.mimeLimit || null; - - this.detectMime = options.detectMime || null; - this.deleteAfterDays = options.deleteAfterDays || null; - this.fileType = options.fileType || null; +// 列举bucket +// @link https://developer.qiniu.com/kodo/api/3926/get-service +// @param callbackFunc(err, respBody, respInfo) 回调函数 +BucketManager.prototype.listBucket = function (callbackFunc) { + var requestURI = 'https://rs.qbox.me/buckets'; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 获取bucket信息 +// @param bucket 空间名 +// @param callbackFunc(err, respBody, respInfo) 回调函数 +BucketManager.prototype.getBucketInfo = function (bucket, callbackFunc) { + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/v2/bucketInfo?bucket=' + bucket; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// rules/add增加bucket规则 +// @param bucket 空间名 +// @param name: 规则名称 bucket 内唯一,长度小于50,不能为空,只能为字母、数字、下划线 +// @param prefix: 同一个 bucket 里面前缀不能重复 +// @param to_line_after_days: 指定文件上传多少天后转低频存储。指定为0表示不转低频存储, +// 小于0表示上传的文件立即变低频存储 +// @param delete_after_days: 指定上传文件多少天后删除,指定为0表示不删除,大于0表示多少天后删除 +// @param history_delete_after_days: 指定文件成为历史版本多少天后删除,指定为0表示不删除, +// 大于0表示多少天后删除 +// @param history_to_line_after_days: 指定文件成为历史版本多少天后转低频存储。指定为0表示不转低频存储 +BucketManager.prototype.putBucketLifecycleRule = function (bucket, options, + callbackFunc) { + PutBucketLifecycleRule(this.mac, this.config, bucket, options, callbackFunc); +}; + +function PutBucketLifecycleRule (mac, config, bucket, options, callbackFunc) { + options = options || {}; + var reqParams = { + bucket: bucket, + name: options.name + }; + + if (options.prefix) { + reqParams.prefix = options.prefix; + } else { + reqParams.prefix = ''; + } + + if (options.to_line_after_days) { + reqParams.to_line_after_days = options.to_line_after_days; + } else { + reqParams.to_line_after_days = 0; + } + + if (options.delete_after_days) { + reqParams.delete_after_days = options.delete_after_days; + } else { + reqParams.delete_after_days = 0; + } + + if (options.history_delete_after_days) { + reqParams.history_delete_after_days = options.history_delete_after_days; + } else { + reqParams.history_delete_after_days = 0; + } + + if (options.history_to_line_after_days) { + reqParams.history_to_line_after_days = options.history_to_line_after_days; + } else { + reqParams.history_to_line_after_days = 0; + } + + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/rules/add?' + reqSpec; + var auth = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, auth, callbackFunc); +} + +// rules/delete 删除bucket规则 +// @param bucket 空间名 +// @param name: 规则名称 bucket 内唯一,长度小于50,不能为空,只能为字母、数字、下划线 +BucketManager.prototype.deleteBucketLifecycleRule = function (bucket, name, callbackFunc) { + var reqParams = { + bucket: bucket, + name: name + }; + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/rules/delete?' + reqSpec; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// rules/update 更新bucket规则 +// @param bucket 空间名 +BucketManager.prototype.updateBucketLifecycleRule = function (bucket, options, callbackFunc) { + options = options || {}; + var reqParams = { + bucket: bucket, + name: options.name + }; + + if (options.prefix) { + reqParams.prefix = options.prefix; + } + + if (options.to_line_after_days) { + reqParams.to_line_after_days = options.to_line_after_days; + } + + if (options.delete_after_days) { + reqParams.delete_after_days = options.delete_after_days; + } + + if (options.history_delete_after_days) { + reqParams.history_delete_after_days = options.history_delete_after_days; + } + + if (options.history_to_line_after_days) { + reqParams.history_to_line_after_days = options.history_to_line_after_days; + } + + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/rules/update?' + reqSpec; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// rules/get 获取bucket规则 +// @param bucket 空间名 +BucketManager.prototype.getBucketLifecycleRule = function (bucket, callbackFunc) { + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/rules/get?bucket=' + bucket; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// events/add 增加事件通知规则 +BucketManager.prototype.putBucketEvent = function (bucket, options, callbackFunc) { + PutBucketEvent(this.mac, this.config, options, bucket, callbackFunc); +}; + +function PutBucketEvent (mac, config, options, bucket, callbackFunc) { + options = options || {}; + var reqParams = { // 必填参数 + bucket: bucket, + name: options.name, + event: options.event, + callbackURL: options.callbackURL + }; + + if (options.prefix) { + reqParams.prefix = options.prefix; + } else { + reqParams.prefix = ''; + } + + if (options.suffix) { + reqParams.suffix = options.suffix; + } else { + reqParams.suffix = ''; + } + + if (options.access_key) { + reqParams.access_key = options.access_key; + } else { + reqParams.access_key = ''; + } + + if (options.host) { + reqParams.host = options.host; + } else { + reqParams.host = ''; + } + + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/events/add?' + reqSpec; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +} + +// events/get 更新事件通知规则 +BucketManager.prototype.updateBucketEvent = function (bucket, options, callbackFunc) { + UpdateBucketEvent(this.mac, this.config, options, bucket, callbackFunc); +}; + +function UpdateBucketEvent (mac, config, options, bucket, callbackFunc) { + options = options || {}; + var reqParams = { + bucket: bucket, + name: options.name + }; + + if (options.prefix) { + reqParams.prefix = options.prefix; + } + + if (options.suffix) { + reqParams.suffix = options.suffix; + } + + if (options.event) { + reqParams.event = options.event; + } + + if (options.callbackURL) { + reqParams.callbackURL = options.callbackURL; + } + + if (options.access_key) { + reqParams.access_key = options.access_key; + } + + if (options.host) { + reqParams.host = options.host; + } + + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/events/update?' + reqSpec; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } -PutPolicy.prototype.getFlags = function() { - var flags = {}; - var attrs = ['scope', 'isPrefixalScope', 'insertOnly', 'saveKey', 'endUser', - 'returnUrl', 'returnBody', 'callbackUrl', 'callbackHost', - 'callbackBody', 'callbackBodyType', 'callbackFetchKey', 'persistentOps', - 'persistentNotifyUrl', 'persistentPipeline', 'fsizeLimit', 'fsizeMin', - 'detectMime', 'mimeLimit', 'deleteAfterDays', 'fileType' - ]; +// events/get 获取事件通知规则 +BucketManager.prototype.getBucketEvent = function (bucket, callbackFunc) { + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/events/get?bucket=' + bucket; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// events/delete 删除事件通知规则 +BucketManager.prototype.deleteBucketEvent = function (bucket, name, callbackFunc) { + var reqParams = { + bucket: bucket, + name: name + }; + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/events/delete?' + reqSpec; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 设置防盗链 +// @param bucket: bucket 名 +// @param mode 0: 表示关闭Referer; 1: 表示设置Referer白名单; 2: 表示设置Referer黑名单 +// @param norefer 0: 表示不允许空 Refer 访问; 1: 表示允许空 Refer 访问 +// @param pattern 一种为空主机头域名, 比如 foo.com; 一种是泛域名, 比如 *.bar.com; +// 一种是完全通配符, 即一个 *; 多个规则之间用;隔开 +// @param source_enabled=: 源站是否支持,默认为0只给CDN配置, 设置为1表示开启源站防盗链 +BucketManager.prototype.putReferAntiLeech = function (bucket, options, callbackFunc) { + PutReferAntiLeech(this.mac, this.config, bucket, options, callbackFunc); +}; + +function PutReferAntiLeech (mac, config, bucket, options, callbackFunc) { + options = options || {}; + var reqParams = { + bucket: bucket + }; + + if (options.mode) { + reqParams.mode = options.mode; + } else { + reqParams.mode = 0; + } + + if (options.norefer) { + reqParams.norefer = options.norefer; + } else { + reqParams.norefer = 0; + } + + if (options.pattern) { + reqParams.pattern = options.pattern; + } else { + reqParams.pattern = '*'; + } - for (var i = attrs.length - 1; i >= 0; i--) { - if (this[attrs[i]] !== null) { - flags[attrs[i]] = this[attrs[i]]; + if (options.source_enabled) { + reqParams.source_enabled = options.source_enabled; + } else { + reqParams.source_enabled = 0; } - } - flags['deadline'] = this.expires + Math.floor(Date.now() / 1000); + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/referAntiLeech?' + reqSpec; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +} + +/// corsRules/set 设置bucket的cors(跨域)规则 +BucketManager.prototype.putCorsRules = function (bucket, body, callbackFunc) { + PutCorsRules(this.mac, this.config, bucket, body, callbackFunc); +}; + +function PutCorsRules (mac, config, bucket, body, callbackFunc) { + var reqBody = JSON.stringify(body); + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/corsRules/set/' + bucket; + var auth = util.generateAccessToken(mac, requestURI, reqBody); + rpc.postWithForm(requestURI, reqBody, auth, callbackFunc); +} + +/// corsRules/get 获取bucket跨域 +BucketManager.prototype.getCorsRules = function (bucket, callbackFunc) { + GetCorsRules(this.mac, this.config, bucket, callbackFunc); +}; - return flags; +function GetCorsRules (mac, config, bucket, callbackFunc) { + var scheme = config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/corsRules/get/' + bucket; + var digest = util.generateAccessToken(mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); } +// BucketManager.prototype.getBucketSourceConfig = function(body, callbackFunc) { +// var reqBody = JSON.stringify(body); +// console.log(reqBody); +// var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; +// var requestURI = scheme + conf.UC_HOST + '/mirrorConfig/get'; +// var digest = util.generateAccessTokenV2(this.mac, requestURI, 'POST', conf.FormMimeJson, reqBody); +// rpc.postWithForm(requestURI, reqBody,digest, callbackFunc); +// } + +// 原图保护 +// @param bucket 空间名称 +// @param mode 为1表示开启原图保护,0表示关闭 +BucketManager.prototype.putBucketAccessStyleMode = function (bucket, mode, callbackFunc) { + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/accessMode/' + bucket + '/mode/' + mode; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 设置Bucket的cache-control: max-age属性 +// @param maxAge:为0或者负数表示为默认值(31536000) +BucketManager.prototype.putBucketMaxAge = function (bucket, options, callbackFunc) { + var maxAge = options.maxAge; + if (maxAge <= 0) { + maxAge = 31536000; + } + var reqParams = { + bucket: bucket, + maxAge: maxAge + }; + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/maxAge?' + reqSpec; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 设置Bucket私有属性 +// @param private为0表示公开,为1表示私有 +BucketManager.prototype.putBucketAccessMode = function (bucket, options, callbackFunc) { + options = options || {}; + var reqParams = { + bucket: bucket + }; + + if (options.private) { + reqParams.private = options.private; + } else { + reqParams.private = 0; + } + + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = querystring.stringify(reqParams); + var requestURI = scheme + conf.UC_HOST + '/private?' + reqSpec; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 设置配额 +// @param bucket: 空间名称,不支持授权空间 +// @param size: 空间存储量配额,参数传入0或不传表示不更改当前配置,传入-1表示取消限额,新创建的空间默认没有限额。 +// @param count: 空间文件数配额,参数含义同 +BucketManager.prototype.putBucketQuota = function (bucket, options, callbackFunc) { + options = options || {}; + var reqParams = { + bucket: bucket + }; + + if (options.size) { + reqParams.size = options.size; + } else { + reqParams.size = 0; + } + + if (options.count) { + reqParams.count = options.count; + } else { + reqParams.count = 0; + } + + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var reqSpec = `${reqParams.bucket}/size/${reqParams.size}/count/${reqParams.count}`; + var requestURI = scheme + conf.UC_HOST + '/setbucketquota/' + reqSpec; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 获取配额 +// @param bucket: 空间名称,不支持授权空间 +BucketManager.prototype.getBucketQuota = function (bucket, callbackFunc) { + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/getbucketquota/' + bucket; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 获得Bucket的所有域名 +// @param bucket:bucketName +BucketManager.prototype.listBucketDomains = function (bucket, callbackFunc) { + var scheme = this.config.useHttpsDomain ? 'https://' : 'http://'; + var requestURI = scheme + conf.UC_HOST + '/v3/domains?tbl=' + bucket; + var digest = util.generateAccessToken(this.mac, requestURI, null); + rpc.postWithoutForm(requestURI, digest, callbackFunc); +}; + +// 上传策略 +// @link https://developer.qiniu.com/kodo/manual/1206/put-policy +function PutPolicy (options) { + if (typeof options !== 'object') { + throw new Error('invalid putpolicy options'); + } + + this.scope = options.scope || null; + this.isPrefixalScope = options.isPrefixalScope || null; + this.expires = options.expires || 3600; + this.insertOnly = options.insertOnly || null; + + this.saveKey = options.saveKey || null; + this.endUser = options.endUser || null; + + this.returnUrl = options.returnUrl || null; + this.returnBody = options.returnBody || null; + + this.callbackUrl = options.callbackUrl || null; + this.callbackHost = options.callbackHost || null; + this.callbackBody = options.callbackBody || null; + this.callbackBodyType = options.callbackBodyType || null; + this.callbackFetchKey = options.callbackFetchKey || null; + + this.persistentOps = options.persistentOps || null; + this.persistentNotifyUrl = options.persistentNotifyUrl || null; + this.persistentPipeline = options.persistentPipeline || null; -PutPolicy.prototype.uploadToken = function(mac) { - mac = mac || new digest.Mac(); - var flags = this.getFlags(); - var encodedFlags = util.urlsafeBase64Encode(JSON.stringify(flags)); - var encoded = util.hmacSha1(encodedFlags, mac.secretKey); - var encodedSign = util.base64ToUrlSafe(encoded); - var uploadToken = mac.accessKey + ':' + encodedSign + ':' + encodedFlags; - return uploadToken; + this.fsizeLimit = options.fsizeLimit || null; + this.fsizeMin = options.fsizeMin || null; + this.mimeLimit = options.mimeLimit || null; + + this.detectMime = options.detectMime || null; + this.deleteAfterDays = options.deleteAfterDays || null; + this.fileType = options.fileType || null; } + +PutPolicy.prototype.getFlags = function () { + var flags = {}; + var attrs = ['scope', 'isPrefixalScope', 'insertOnly', 'saveKey', 'endUser', + 'returnUrl', 'returnBody', 'callbackUrl', 'callbackHost', + 'callbackBody', 'callbackBodyType', 'callbackFetchKey', 'persistentOps', + 'persistentNotifyUrl', 'persistentPipeline', 'fsizeLimit', 'fsizeMin', + 'detectMime', 'mimeLimit', 'deleteAfterDays', 'fileType' + ]; + + for (var i = attrs.length - 1; i >= 0; i--) { + if (this[attrs[i]] !== null) { + flags[attrs[i]] = this[attrs[i]]; + } + } + + flags.deadline = this.expires + Math.floor(Date.now() / 1000); + + return flags; +}; + +PutPolicy.prototype.uploadToken = function (mac) { + mac = mac || new digest.Mac(); + var flags = this.getFlags(); + var encodedFlags = util.urlsafeBase64Encode(JSON.stringify(flags)); + var encoded = util.hmacSha1(encodedFlags, mac.secretKey); + var encodedSign = util.base64ToUrlSafe(encoded); + var uploadToken = mac.accessKey + ':' + encodedSign + ':' + encodedFlags; + return uploadToken; +}; diff --git a/qiniu/util.js b/qiniu/util.js index 2f30ef9f..1117bc56 100644 --- a/qiniu/util.js +++ b/qiniu/util.js @@ -1,86 +1,129 @@ -var url = require('url'); -var crypto = require('crypto'); -var conf = require('./conf'); +const url = require('url'); +const crypto = require('crypto'); +const zone = require('./zone'); // Check Timestamp Expired or not -exports.isTimestampExpired = function(timestamp) { - return timestamp < parseInt(Date.now() / 1000); -} +exports.isTimestampExpired = function (timestamp) { + return timestamp < parseInt(Date.now() / 1000); +}; // Encoded Entry -exports.encodedEntry = function(bucket, key) { - return exports.urlsafeBase64Encode(bucket + (key ? ':' + key : '')); -} +exports.encodedEntry = function (bucket, key) { + return exports.urlsafeBase64Encode(bucket + (key ? ':' + key : '')); +}; // Get accessKey from uptoken -exports.getAKFromUptoken = function(uploadToken) { - var sepIndex = uploadToken.indexOf(":"); - return uploadToken.substring(0, sepIndex); -} +exports.getAKFromUptoken = function (uploadToken) { + var sepIndex = uploadToken.indexOf(':'); + return uploadToken.substring(0, sepIndex); +}; // Get bucket from uptoken -exports.getBucketFromUptoken = function(uploadToken) { - var sepIndex = uploadToken.lastIndexOf(":"); - var encodedPutPolicy = uploadToken.substring(sepIndex + 1); - var putPolicy = exports.urlSafeBase64Decode(encodedPutPolicy); - var putPolicyObj = JSON.parse(putPolicy); - var scope = putPolicyObj.scope; - var scopeSepIndex = scope.indexOf(":"); - if (scopeSepIndex == -1) { - return scope; - } else { - return scope.substring(0, scopeSepIndex); - } -} - - -exports.base64ToUrlSafe = function(v) { - return v.replace(/\//g, '_').replace(/\+/g, '-'); -} - -exports.urlSafeToBase64 = function(v) { - return v.replace(/\_/g, '/').replace(/\-/g, '+'); -} +exports.getBucketFromUptoken = function (uploadToken) { + var sepIndex = uploadToken.lastIndexOf(':'); + var encodedPutPolicy = uploadToken.substring(sepIndex + 1); + var putPolicy = exports.urlSafeBase64Decode(encodedPutPolicy); + var putPolicyObj = JSON.parse(putPolicy); + var scope = putPolicyObj.scope; + var scopeSepIndex = scope.indexOf(':'); + if (scopeSepIndex == -1) { + return scope; + } else { + return scope.substring(0, scopeSepIndex); + } +}; + +exports.base64ToUrlSafe = function (v) { + return v.replace(/\//g, '_').replace(/\+/g, '-'); +}; + +exports.urlSafeToBase64 = function (v) { + return v.replace(/_/g, '/').replace(/-/g, '+'); +}; // UrlSafe Base64 Decode -exports.urlsafeBase64Encode = function(jsonFlags) { - var encoded = new Buffer(jsonFlags).toString('base64'); - return exports.base64ToUrlSafe(encoded); -} +exports.urlsafeBase64Encode = function (jsonFlags) { + var encoded = Buffer.from(jsonFlags).toString('base64'); + return exports.base64ToUrlSafe(encoded); +}; // UrlSafe Base64 Decode -exports.urlSafeBase64Decode = function(fromStr) { - return new Buffer(exports.urlSafeToBase64(fromStr), 'base64').toString(); -} +exports.urlSafeBase64Decode = function (fromStr) { + return Buffer.from(exports.urlSafeToBase64(fromStr), 'base64').toString(); +}; // Hmac-sha1 Crypt -exports.hmacSha1 = function(encodedFlags, secretKey) { - /* +exports.hmacSha1 = function (encodedFlags, secretKey) { + /* *return value already encoded with base64 * */ - var hmac = crypto.createHmac('sha1', secretKey); - hmac.update(encodedFlags); - return hmac.digest('base64'); -} + var hmac = crypto.createHmac('sha1', secretKey); + hmac.update(encodedFlags); + return hmac.digest('base64'); +}; -// 创建AccessToken凭证 +// 创建 AccessToken 凭证 // @param mac AK&SK对象 -// @param requestURI 回调的URL中的requestURI -// @param reqBody 请求Body,仅当请求的ContentType为 +// @param requestURI 请求URL +// @param reqBody 请求Body,仅当请求的 ContentType 为 // application/x-www-form-urlencoded时才需要传入该参数 -exports.generateAccessToken = function(mac, requestURI, reqBody) { - var u = url.parse(requestURI); - var path = u.path; - var access = path + '\n'; +exports.generateAccessToken = function (mac, requestURI, reqBody) { + var u = new url.URL(requestURI); + var path = u.pathname + u.search; + var access = path + '\n'; + + if (reqBody) { + access += reqBody; + } + + var digest = exports.hmacSha1(access, mac.secretKey); + var safeDigest = exports.base64ToUrlSafe(digest); + return 'QBox ' + mac.accessKey + ':' + safeDigest; +}; + +// 创建 AccessToken 凭证 +// @param mac AK&SK对象 +// @param requestURI 请求URL +// @param reqMethod 请求方法,例如 GET,POST +// @param reqContentType 请求类型,例如 application/json 或者 application/x-www-form-urlencoded +// @param reqBody 请求Body,仅当请求的 ContentType 为 application/json 或者 +// application/x-www-form-urlencoded 时才需要传入该参数 +exports.generateAccessTokenV2 = function (mac, requestURI, reqMethod, reqContentType, reqBody) { + var u = new url.URL(requestURI); + var path = u.pathname; + var search = u.search; + var host = u.host; + var port = u.port; + + var access = reqMethod.toUpperCase() + ' ' + path; + if (search) { + access += search; + } + // add host + access += '\nHost: ' + host; + // add port + if (port) { + access += ':' + port; + } - if (reqBody) { - access += reqBody; - } + // add content type + if (reqContentType && (reqContentType == 'application/json' || reqContentType == 'application/x-www-form-urlencoded')) { + access += '\nContent-Type: ' + reqContentType; + } - var digest = exports.hmacSha1(access, mac.secretKey); - var safeDigest = exports.base64ToUrlSafe(digest); - return 'QBox ' + mac.accessKey + ':' + safeDigest; -} + access += '\n\n'; + + // add reqbody + if (reqBody) { + access += reqBody; + } + + // console.log(access); + + var digest = exports.hmacSha1(access, mac.secretKey); + var safeDigest = exports.base64ToUrlSafe(digest); + return 'Qiniu ' + mac.accessKey + ':' + safeDigest; +}; // 校验七牛上传回调的Authorization // @param mac AK&SK对象 @@ -88,7 +131,36 @@ exports.generateAccessToken = function(mac, requestURI, reqBody) { // @param reqBody 请求Body,仅当请求的ContentType为 // application/x-www-form-urlencoded时才需要传入该参数 // @param callbackAuth 回调时请求的Authorization头部值 -exports.isQiniuCallback = function(mac, requestURI, reqBody, callbackAuth) { - var auth = exports.generateAccessToken(mac, requestURI, reqBody); - return auth === callbackAuth; -} +exports.isQiniuCallback = function (mac, requestURI, reqBody, callbackAuth) { + var auth = exports.generateAccessToken(mac, requestURI, reqBody); + return auth === callbackAuth; +}; + +exports.prepareZone = function (ctx, accessKey, bucket, callback) { + var useCache = false; + if (ctx.config.zone != '' && ctx.config.zone != null) { + if (ctx.config.zoneExpire == -1) { + useCache = true; + } else { + if (!exports.isTimestampExpired(ctx.config.zoneExpire)) { + useCache = true; + } + } + } + + if (useCache) { + callback(null, ctx); + } else { + zone.getZoneInfo(accessKey, bucket, function (err, cZoneInfo, + cZoneExpire) { + if (err) { + callback(err); + return; + } + // update object + ctx.config.zone = cZoneInfo; + ctx.config.zoneExpire = cZoneExpire + parseInt(Date.now() / 1000); + callback(null, ctx); + }); + } +}; diff --git a/qiniu/zone.js b/qiniu/zone.js index b78e7784..f56bc43a 100644 --- a/qiniu/zone.js +++ b/qiniu/zone.js @@ -1,105 +1,112 @@ -const urllib = require('urllib') -const util = require('util') +const urllib = require('urllib'); +const util = require('util'); const conf = require('./conf'); -//huadong +// huadong exports.Zone_z0 = new conf.Zone([ 'up.qiniup.com', 'up-nb.qiniup.com', - 'up-xs.qiniup.com', - ], [ + 'up-xs.qiniup.com' +], [ 'upload.qiniup.com', 'upload-nb.qiniup.com', - 'upload-xs.qiniup.com', - ], 'iovip.qbox.me', - 'rs.qiniu.com', - 'rsf.qiniu.com', - 'api.qiniu.com'); + 'upload-xs.qiniup.com' +], 'iovip.qbox.me', +'rs.qbox.me', +'rsf.qbox.me', +'api.qiniu.com'); -//huabei +// huabei exports.Zone_z1 = new conf.Zone([ - 'up-z1.qiniup.com', - ], [ - 'upload-z1.qiniup.com', - ], 'iovip-z1.qbox.me', - 'rs-z1.qiniu.com', - 'rsf-z1.qiniu.com', - 'api-z1.qiniu.com'); + 'up-z1.qiniup.com' +], [ + 'upload-z1.qiniup.com' +], 'iovip-z1.qbox.me', +'rs-z1.qbox.me', +'rsf-z1.qbox.me', +'api-z1.qiniu.com'); -//huanan +// huanan exports.Zone_z2 = new conf.Zone([ 'up-z2.qiniup.com', 'up-gz.qiniup.com', 'up-fs.qiniup.com' - ], [ +], [ 'upload-z2.qiniup.com', 'upload-gz.qiniup.com', - 'upload-fs.qiniup.com', - ], 'iovip-z2.qbox.me', - 'rs-z2.qiniu.com', - 'rsf-z2.qiniu.com', - 'api-z2.qiniu.com'); + 'upload-fs.qiniup.com' +], 'iovip-z2.qbox.me', +'rs-z2.qbox.me', +'rsf-z2.qbox.me', +'api-z2.qiniu.com'); - -//beimei +// beimei exports.Zone_na0 = new conf.Zone([ - 'up-na0.qiniup.com', - ], [ - 'upload-na0.qiniup.com', - ], 'iovip-na0.qbox.me', - 'rs-na0.qiniu.com', - 'rsf-na0.qiniu.com', - 'api-na0.qiniu.com') + 'up-na0.qiniup.com' +], [ + 'upload-na0.qiniup.com' +], 'iovip-na0.qbox.me', +'rs-na0.qbox.me', +'rsf-na0.qbox.me', +'api-na0.qiniu.com'); +exports.Zone_as0 = new conf.Zone([ + 'up-as0.qiniup.com' +], [ + 'upload-as0.qiniup.com' +], 'iovip-as0.qbox.me', +'rs-as0.qbox.me', +'rsf-as0.qbox.me', +'api-as0.qiniu.com'); -exports.getZoneInfo = function(accessKey, bucket, callbackFunc) { - var apiAddr = util.format('http://uc.qbox.me/v2/query?ak=%s&bucket=%s', - accessKey, bucket); - urllib.request(apiAddr, function(respErr, respData, respInfo) { - if (respErr) { - callback(respErr, null, null); - return; - } +exports.getZoneInfo = function (accessKey, bucket, callbackFunc) { + var apiAddr = util.format('https://uc.qbox.me/v2/query?ak=%s&bucket=%s', + accessKey, bucket); + urllib.request(apiAddr, function (respErr, respData, respInfo) { + if (respErr) { + callbackFunc(respErr, null, null); + return; + } - if (respInfo.statusCode != 200) { - //not ok - respErr = new Error(respInfo.statusCode + "\n" + respData); - callbackFunc(respErr, null, null); - return; - } + if (respInfo.statusCode != 200) { + // not ok + respErr = new Error(respInfo.statusCode + '\n' + respData); + callbackFunc(respErr, null, null); + return; + } - var zoneData = JSON.parse(respData); - var srcUpHosts = []; - var cdnUpHosts = []; - var zoneExpire = 0; + var zoneData = JSON.parse(respData); + var srcUpHosts = []; + var cdnUpHosts = []; + var zoneExpire = 0; - try { - zoneExpire = zoneData.ttl; - //read src hosts - zoneData.up.src.main.forEach(function(host) { - srcUpHosts.push(host); - }); - if (zoneData.up.src.backup) { - zoneData.up.src.backup.forEach(function(host) { - srcUpHosts.push(host); - }); - } + try { + zoneExpire = zoneData.ttl; + // read src hosts + zoneData.up.src.main.forEach(function (host) { + srcUpHosts.push(host); + }); + if (zoneData.up.src.backup) { + zoneData.up.src.backup.forEach(function (host) { + srcUpHosts.push(host); + }); + } - //read acc hosts - zoneData.up.acc.main.forEach(function(host) { - cdnUpHosts.push(host); - }); - if (zoneData.up.acc.backup) { - zoneData.up.acc.backup.forEach(function(host) { - cdnUpHosts.push(host); - }); - } + // read acc hosts + zoneData.up.acc.main.forEach(function (host) { + cdnUpHosts.push(host); + }); + if (zoneData.up.acc.backup) { + zoneData.up.acc.backup.forEach(function (host) { + cdnUpHosts.push(host); + }); + } - var ioHost = zoneData.io.src.main[0]; - var zoneInfo = new conf.Zone(srcUpHosts, cdnUpHosts, ioHost) - callbackFunc(null, zoneInfo, zoneExpire); - } catch (e) { - callbackFunc(e, null, null); - } - }); -} + var ioHost = zoneData.io.src.main[0]; + var zoneInfo = new conf.Zone(srcUpHosts, cdnUpHosts, ioHost); + callbackFunc(null, zoneInfo, zoneExpire); + } catch (e) { + callbackFunc(e, null, null); + } + }); +}; diff --git a/test-env.sh b/test-env.sh index c089a872..8833bcbf 100644 --- a/test-env.sh +++ b/test-env.sh @@ -2,3 +2,6 @@ export QINIU_ACCESS_KEY="" export QINIU_SECRET_KEY="" export QINIU_TEST_BUCKET="" export QINIU_TEST_DOMAIN="" + +export QINIU_PILI_ACCESS_KEY="" +export QINIU_PILI_SECRET_KEY="" diff --git a/test/cdn.test.js b/test/cdn.test.js new file mode 100644 index 00000000..16fbc840 --- /dev/null +++ b/test/cdn.test.js @@ -0,0 +1,113 @@ +const qiniu = require('../index.js'); +const should = require('should'); +const proc = require('process'); +const console = require('console'); + +// eslint-disable-next-line no-undef +before(function (done) { + if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || !process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { + console.log('should run command `source test-env.sh` first\n'); + process.exit(0); + } + done(); +}); + +// eslint-disable-next-line no-undef +describe('test start cdn', function () { + var accessKey = proc.env.QINIU_ACCESS_KEY; + var secretKey = proc.env.QINIU_SECRET_KEY; + var domain = proc.env.QINIU_TEST_DOMAIN; + var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); + var cdnManager = new qiniu.cdn.CdnManager(mac); + + it('test getCdnLogList', function (done) { + var day = (new Date()).toISOString().substring(0, 10); + cdnManager.getCdnLogList([domain], day, + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('code', 'data'); + done(); + }); + }); + + it('test getFluxData', function (done) { + var today = new Date(); + var endDay = today.toISOString().substring(0, 10); + today.setDate(today.getDate() - 30); + var startDay = today.toISOString().substring(0, 10); + cdnManager.getFluxData(startDay, endDay, '5hour', [domain], + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('code', 'data'); + done(); + }); + }); + + it('test getBandwidthData', function (done) { + var today = new Date(); + var endDay = today.toISOString().substring(0, 10); + today.setDate(today.getDate() - 30); + var startDay = today.toISOString().substring(0, 10); + cdnManager.getBandwidthData(startDay, endDay, '5hour', [domain], + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('code', 'data'); + done(); + }); + }); + + it('test prefetchUrls', function (done) { + var urls = ['http://' + domain + '/qiniu.mp4']; + cdnManager.prefetchUrls(urls, + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('code', 'taskIds', 'requestId'); + done(); + }); + }); + + it('test refreshUrls', function (done) { + var urls = ['http://' + domain + '/qiniu.mp4']; + cdnManager.refreshUrls(urls, + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('code', 'taskIds', 'requestId'); + done(); + }); + }); + + it('test refreshDirs', function (done) { + var dirs = ['http://' + domain + '/']; + cdnManager.refreshDirs(dirs, + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('code', 'taskIds', 'requestId'); + done(); + }); + }); + + it('test refreshUrlsAndDirs', function (done) { + var urls = ['http://' + domain + '/qiniu.mp4']; + var dirs = ['http://' + domain + '/']; + cdnManager.refreshUrlsAndDirs(urls, dirs, + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('code', 'taskIds', 'requestId'); + done(); + }); + }); + + it('test createTimestampAntiLeechUrl', function (done) { + var host = 'http://' + domain; + var url = cdnManager.createTimestampAntiLeechUrl(host, 'qiniu.mp4', 'aa=23', 'encryptKey', 20); + should.equal(url, host + '/qiniu.mp4?aa=23&sign=1a530a8baafe126145f49cb738a50c09&t=14'); + done(); + }); +}); diff --git a/test/fop.test.js b/test/fop.test.js index 4a9b3109..2832c71a 100644 --- a/test/fop.test.js +++ b/test/fop.test.js @@ -1,54 +1,72 @@ - const qiniu = require("../index.js"); - const should = require('should'); - const proc = require("process"); - - before(function(done) { - if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || ! - process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { - console.log('should run command `source test-env.sh` first\n'); - process.exit(0); +const qiniu = require('../index.js'); +const should = require('should'); +const proc = require('process'); +const console = require('console'); + +// eslint-disable-next-line no-undef +before(function (done) { + if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || !process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { + console.log('should run command `source test-env.sh` first\n'); + process.exit(0); } done(); - }); +}); - describe('test start fop', function() { +// eslint-disable-next-line no-undef +describe('test start fop', function () { var accessKey = proc.env.QINIU_ACCESS_KEY; var secretKey = proc.env.QINIU_SECRET_KEY; var srcBucket = proc.env.QINIU_TEST_BUCKET; var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); var config = new qiniu.conf.Config(); - //config.useHttpsDomain = true; + // config.useHttpsDomain = true; config.zone = qiniu.zone.Zone_z0; - it('test video fop', function(done) { - console.log(srcBucket); - - var pipeline = 'sdktest'; - var srcKey = 'qiniu.mp4'; - var operManager = new qiniu.fop.OperationManager(mac, config); - - //处理指令集合 - var saveBucket = srcBucket; - var fops = [ - 'avthumb/mp4/s/480x320/vb/150k|saveas/' + qiniu.util.urlsafeBase64Encode( - saveBucket + ":qiniu_480x320.mp4"), - 'vframe/jpg/offset/10|saveas/' + qiniu.util.urlsafeBase64Encode( - saveBucket + - ":qiniu_frame1.jpg") - ]; - - var options = { - 'notifyURL': 'http://api.example.com/pfop/callback', - 'force': false, - }; - - //持久化数据处理返回的是任务的persistentId,可以根据这个id查询处理状态 - operManager.pfop(srcBucket, srcKey, fops, pipeline, options, - function(err, respBody, respInfo) { - console.log(respBody); - should.not.exist(err); - respBody.should.have.keys('persistentId'); - done(); - }); + var persistentId; + + it('test video fop', function (done) { + console.log(srcBucket); + + var pipeline = 'sdktest'; + var srcKey = 'qiniu.mp4'; + var operManager = new qiniu.fop.OperationManager(mac, config); + + // 处理指令集合 + var saveBucket = srcBucket; + var fops = [ + 'avthumb/mp4/s/480x320/vb/150k|saveas/' + qiniu.util.urlsafeBase64Encode( + saveBucket + ':qiniu_480x320.mp4'), + 'vframe/jpg/offset/10|saveas/' + qiniu.util.urlsafeBase64Encode( + saveBucket + + ':qiniu_frame1.jpg') + ]; + + var options = { + notifyURL: 'http://api.example.com/pfop/callback', + force: false + }; + + // 持久化数据处理返回的是任务的persistentId,可以根据这个id查询处理状态 + operManager.pfop(srcBucket, srcKey, fops, pipeline, options, + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('persistentId'); + persistentId = respBody.persistentId; + done(); + }); + }); + + it('test video prefop', function (done) { + var operManager = new qiniu.fop.OperationManager(mac, config); + // 查询处理状态 + operManager.prefop(persistentId, + function (err, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('id', 'pipeline', 'inputBucket', 'inputKey'); + respBody.should.have.property('id', persistentId); + done(); + }); }); - }); +}); diff --git a/test/form_up.test.js b/test/form_up.test.js index 2d56e1f1..0223e5ed 100644 --- a/test/form_up.test.js +++ b/test/form_up.test.js @@ -1,156 +1,167 @@ const path = require('path'); const should = require('should'); -const assert = require('assert'); -const qiniu = require("../index.js"); -const proc = require("process"); -const fs = require("fs"); +// const assert = require('assert'); +const qiniu = require('../index.js'); +const proc = require('process'); +const fs = require('fs'); +const console = require('console'); -before(function(done) { - if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || ! - process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { - console.log('should run command `source test-env.sh` first\n'); - process.exit(0); - } - done(); +// eslint-disable-next-line no-undef +before(function (done) { + if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || !process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { + console.log('should run command `source test-env.sh` first\n'); + process.exit(0); + } + done(); }); - -//file to upload +// file to upload var testFilePath1 = path.join(__dirname, 'logo.png'); var testFilePath2 = path.join(__dirname, 'github.png'); -describe('test form up', function() { - var accessKey = proc.env.QINIU_ACCESS_KEY; - var secretKey = proc.env.QINIU_SECRET_KEY; - var bucket = proc.env.QINIU_TEST_BUCKET; - var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); - var config = new qiniu.conf.Config(); - //config.useHttpsDomain = true; - config.zone = qiniu.zone.Zone_z0; - var bucketManager = new qiniu.rs.BucketManager(mac, config); +// eslint-disable-next-line no-undef +describe('test form up', function () { + var accessKey = proc.env.QINIU_ACCESS_KEY; + var secretKey = proc.env.QINIU_SECRET_KEY; + var bucket = proc.env.QINIU_TEST_BUCKET; + var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); + var config = new qiniu.conf.Config(); + // config.useHttpsDomain = true; + config.zone = qiniu.zone.Zone_z0; + var bucketManager = new qiniu.rs.BucketManager(mac, config); - //delete all the files uploaded - var keysToDelete = []; + // delete all the files uploaded + var keysToDelete = []; - after(function(done) { - var deleteOps = []; - keysToDelete.forEach(function(key) { - deleteOps.push(qiniu.rs.deleteOp(bucket, key)); - }); + // eslint-disable-next-line no-undef + after(function (done) { + var deleteOps = []; + keysToDelete.forEach(function (key) { + deleteOps.push(qiniu.rs.deleteOp(bucket, key)); + }); - bucketManager.batch(deleteOps, function(respErr, respBody, respInfo) { - //console.log(respBody); - respBody.forEach(function(ret) { - ret.should.eql({ - code: 200 + bucketManager.batch(deleteOps, function (respErr, respBody) { + // console.log(respBody); + respBody.forEach(function (ret) { + ret.should.eql({ + code: 200 + }); + }); + done(); }); - }); - done(); }); - }); - var options = { - scope: bucket, - } - var putPolicy = new qiniu.rs.PutPolicy(options); - var uploadToken = putPolicy.uploadToken(mac); - var config = new qiniu.conf.Config(); - config.zone = qiniu.zone.Zone_z0; - var formUploader = new qiniu.form_up.FormUploader(config); - var putExtra = new qiniu.form_up.PutExtra(); + var options = { + scope: bucket + }; + var putPolicy = new qiniu.rs.PutPolicy(options); + var uploadToken = putPolicy.uploadToken(mac); + config.zone = qiniu.zone.Zone_z0; + var formUploader = new qiniu.form_up.FormUploader(config); + var putExtra = new qiniu.form_up.PutExtra(); - describe('test form up#putStreamWithoutKey', function() { - it('test form up#putStreamWithoutKey', function(done) { - var key = null; - var rs = fs.createReadStream(testFilePath1); - formUploader.putStream(uploadToken, key, rs, putExtra, - function(respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test form up#putStreamWithoutKey', function () { + // eslint-disable-next-line no-undef + it('test form up#putStreamWithoutKey', function (done) { + var key = null; + var rs = fs.createReadStream(testFilePath1); + formUploader.putStream(uploadToken, key, rs, putExtra, + function (respErr, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); - describe('test form up#putStream', function() { - it('test form up#putStream', function(done) { - var key = 'storage_putStream_test' + Math.random(1000); - var rs = fs.createReadStream(testFilePath1); - formUploader.putStream(uploadToken, key, rs, putExtra, - function(respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test form up#putStream', function () { + // eslint-disable-next-line no-undef + it('test form up#putStream', function (done) { + var key = 'storage_putStream_test' + Math.random(1000); + var rs = fs.createReadStream(testFilePath1); + formUploader.putStream(uploadToken, key, rs, putExtra, + function (respErr, respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); - describe('test form up#put', function() { - it('test form up#put', function(done) { - var key = 'storage_put_test' + Math.random(1000); - formUploader.put(uploadToken, key, "hello world", putExtra, - function(respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test form up#put', function () { + // eslint-disable-next-line no-undef + it('test form up#put', function (done) { + var key = 'storage_put_test' + Math.random(1000); + formUploader.put(uploadToken, key, 'hello world', putExtra, + function (respErr, + respBody) { + // console.log(respBody); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); - describe('test form up#putWithoutKey', function() { - it('test form up#putWithoutKey', function(done) { - formUploader.putWithoutKey(uploadToken, "hello world", - putExtra, - function(respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test form up#putWithoutKey', function () { + // eslint-disable-next-line no-undef + it('test form up#putWithoutKey', function (done) { + formUploader.putWithoutKey(uploadToken, 'hello world', + putExtra, + function (respErr, + respBody) { + // console.log(respBody); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); - describe('test form up#putFile', function() { - it('test form up#putFile', function(done) { - var key = 'storage_putFile_test' + Math.random(1000); - formUploader.putFile(uploadToken, key, testFilePath2, - putExtra, - function( - respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test form up#putFile', function () { + // eslint-disable-next-line no-undef + it('test form up#putFile', function (done) { + var key = 'storage_putFile_test' + Math.random(1000); + formUploader.putFile(uploadToken, key, testFilePath2, + putExtra, + function ( + respErr, + respBody) { + // console.log(respBody); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); - describe('test form up#putFileWithoutKey', function() { - it('test form up#putFileWithoutKey', function(done) { - formUploader.putFileWithoutKey(uploadToken, testFilePath2, - putExtra, - function( - respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test form up#putFileWithoutKey', function () { + // eslint-disable-next-line no-undef + it('test form up#putFileWithoutKey', function (done) { + formUploader.putFileWithoutKey(uploadToken, testFilePath2, + putExtra, + function ( + respErr, + respBody) { + // console.log(respBody); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); }); diff --git a/test/resume_up.test.js b/test/resume_up.test.js index 1f6d5405..b91b808b 100644 --- a/test/resume_up.test.js +++ b/test/resume_up.test.js @@ -1,92 +1,158 @@ +const os = require('os'); +const fs = require('fs'); const path = require('path'); const should = require('should'); -const assert = require('assert'); -const qiniu = require("../index.js"); -const proc = require("process"); -const fs = require("fs"); +const qiniu = require('../index.js'); +const proc = require('process'); +const console = require('console'); +const crypto = require('crypto'); +const Readable = require('stream').Readable; -before(function(done) { - if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || ! - process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { - console.log('should run command `source test-env.sh` first\n'); - process.exit(0); - } - done(); +// eslint-disable-next-line no-undef +before(function (done) { + if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || !process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { + console.log('should run command `source test-env.sh` first\n'); + process.exit(0); + } + done(); }); - -//file to upload +// file to upload var imageFile = path.join(__dirname, 'logo.png'); -describe('test resume up', function() { - var accessKey = proc.env.QINIU_ACCESS_KEY; - var secretKey = proc.env.QINIU_SECRET_KEY; - var bucket = proc.env.QINIU_TEST_BUCKET; - var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); - var config = new qiniu.conf.Config(); - //config.useHttpsDomain = true; - config.zone = qiniu.zone.Zone_z0; - var bucketManager = new qiniu.rs.BucketManager(mac, config); +// eslint-disable-next-line no-undef +describe('test resume up', function () { + var accessKey = proc.env.QINIU_ACCESS_KEY; + var secretKey = proc.env.QINIU_SECRET_KEY; + var bucket = proc.env.QINIU_TEST_BUCKET; + var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); + var config = new qiniu.conf.Config(); + // config.useHttpsDomain = true; + config.zone = qiniu.zone.Zone_z0; + var bucketManager = new qiniu.rs.BucketManager(mac, config); - //delete all the files uploaded - var keysToDelete = []; + // delete all the files uploaded + var keysToDelete = []; - after(function(done) { - var deleteOps = []; - keysToDelete.forEach(function(key) { - deleteOps.push(qiniu.rs.deleteOp(bucket, key)); - }); + // eslint-disable-next-line no-undef + after(function (done) { + var deleteOps = []; + keysToDelete.forEach(function (key) { + deleteOps.push(qiniu.rs.deleteOp(bucket, key)); + }); - bucketManager.batch(deleteOps, function(respErr, respBody, respInfo) { - //console.log(respBody); - respBody.forEach(function(ret) { - ret.should.eql({ - code: 200 + bucketManager.batch(deleteOps, function (respErr, respBody, respInfo) { + console.log(respBody, respInfo); + respBody.forEach(function (ret) { + ret.should.eql({ + code: 200 + }); + }); + done(); }); - }); - done(); }); - }); - var options = { - scope: bucket, - } - var putPolicy = new qiniu.rs.PutPolicy(options); - var uploadToken = putPolicy.uploadToken(mac); - var config = new qiniu.conf.Config(); - config.zone = qiniu.zone.Zone_z0; - var resumeUploader = new qiniu.resume_up.ResumeUploader(config); - var putExtra = new qiniu.resume_up.PutExtra(); + var options = { + scope: bucket + }; + var putPolicy = new qiniu.rs.PutPolicy(options); + var uploadToken = putPolicy.uploadToken(mac); + config.zone = qiniu.zone.Zone_z0; + var resumeUploader = new qiniu.resume_up.ResumeUploader(config); + var putExtra = new qiniu.resume_up.PutExtra(); - describe('test resume up#putFileWithoutKey', function() { - it('test resume up#putFileWithoutKey', function(done) { - resumeUploader.putFileWithoutKey(uploadToken, imageFile, - putExtra, - function( - respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test resume up#putFileWithoutKey', function () { + // eslint-disable-next-line no-undef + it('test resume up#putFileWithoutKey', function (done) { + resumeUploader.putFileWithoutKey(uploadToken, imageFile, + putExtra, + function ( + respErr, + respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); - describe('test resume up#putFile', function() { - it('test resume up#putFile', function(done) { - var key = 'storage_putFile_test' + Math.random(1000); - resumeUploader.putFile(uploadToken, key, imageFile, putExtra, - function( - respErr, - respBody, respInfo) { - //console.log(respBody); - should.not.exist(respErr); - respBody.should.have.keys('key', 'hash'); - keysToDelete.push(respBody.key); - done(); + // eslint-disable-next-line no-undef + describe('test resume up#putFile', function () { + // eslint-disable-next-line no-undef + it('test resume up#putFile', function (done) { + var key = 'storage_putFile_test' + Math.random(1000); + resumeUploader.putFile(uploadToken, key, imageFile, putExtra, + function ( + respErr, + respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); + }); + }); + + describe('test resume up#putStream', function () { + // eslint-disable-next-line no-undef + it('test resume up#putStream', function (done) { + var key = 'storage_putStream_test' + Math.random(1000); + var stream = new Readable(); + var blkSize = 1024 * 1024; + var blkCnt = 9; + for (var i = 0; i < blkCnt; i++) { + stream.push(crypto.randomBytes(blkSize)); + } + stream.push(null); + resumeUploader.putStream(uploadToken, key, stream, blkCnt * blkSize, putExtra, + function ( + respErr, + respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); + }); + + it('test resume up#putStream resume', function (done) { + config.zone = null; + + var key = 'storage_putStream_resume_test' + Math.random(1000); + var stream = new Readable(); + var blkSize = 1024 * 1024; + var blkCnt = 5; + for (var i = 0; i < blkCnt; i++) { + stream.push(crypto.randomBytes(blkSize)); + } + stream.push(null); + var tmpfile = path.join(os.tmpdir(), '/resume_file'); + fs.writeFileSync(tmpfile, ''); + putExtra.resumeRecordFile = tmpfile; + putExtra.progressCallback = function (len, total) { + if (len === total) { + var content = fs.readFileSync(tmpfile); + var data = JSON.parse(content); + data.forEach(function (item) { + item.should.have.keys('ctx', 'expired_at', 'crc32'); + }); + } + }; + resumeUploader.putStream(uploadToken, key, stream, blkCnt * blkSize, putExtra, + function ( + respErr, + respBody, respInfo) { + console.log(respBody, respInfo); + should.not.exist(respErr); + respBody.should.have.keys('key', 'hash'); + keysToDelete.push(respBody.key); + done(); + }); }); }); - }); }); diff --git a/test/rs.test.js b/test/rs.test.js index 78b5bf5e..f2ae8a7b 100644 --- a/test/rs.test.js +++ b/test/rs.test.js @@ -1,108 +1,604 @@ const should = require('should'); const assert = require('assert'); -const qiniu = require("../index.js"); -const proc = require("process"); - -before(function(done) { - if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || ! - process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { - console.log('should run command `source test-env.sh` first\n'); - process.exit(0); - } - done(); +const qiniu = require('../index.js'); +const proc = require('process'); +const urllib = require('urllib'); +const console = require('console'); + +// eslint-disable-next-line no-undef +before(function (done) { + if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || !process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { + console.log('should run command `source test-env.sh` first\n'); + process.exit(0); + } + done(); }); -describe('test start bucket manager', function() { - var accessKey = proc.env.QINIU_ACCESS_KEY; - var secretKey = proc.env.QINIU_SECRET_KEY; - var srcBucket = proc.env.QINIU_TEST_BUCKET; - var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); - var config = new qiniu.conf.Config(); - //config.useHttpsDomain = true; - config.zone = qiniu.zone.Zone_z0; - var bucketManager = new qiniu.rs.BucketManager(mac, config); - //test stat - describe('test stat', function() { - it('test stat', function(done) { - var bucket = srcBucket; - var key = 'qiniu.mp4'; - bucketManager.stat(bucket, key, function(err, respBody, - respInfo) { - //console.log(respBody); - should.not.exist(err); - respBody.should.have.keys('hash', 'fsize', 'mimeType', - 'putTime', 'type'); - done(); - }); - }); - }); - - //test copy and move and delete - describe('test copy', function() { - it('test copy', function(done) { - var destBucket = srcBucket; - var srcKey = 'qiniu.mp4'; - var destKey = 'qiniu_copy.mp4'; - var options = { - force: true, - } - bucketManager.copy(srcBucket, srcKey, destBucket, destKey, - options, - function(err, respBody, respInfo) { - //console.log(respBody); - should.not.exist(err); - assert.equal(respInfo.statusCode, 200); - done(); - - //test move - describe('test move', function() { - var moveDestKey = 'qiniu_move.mp4'; - it('test move', function(done1) { - bucketManager.move(destBucket, destKey, - destBucket, moveDestKey, options, - function(err1, ret1, info1) { - should.not.exist(err1); - assert.equal(info1.statusCode, 200); - done1(); - - //test delete - describe('test delete', function() { - it('test delete', function( - done2) { - bucketManager.delete( - destBucket, - moveDestKey, - function(err2, ret2, - info2) { - should.not.exist( - err2); - assert.equal(info2.statusCode, - 200); - done2(); +// eslint-disable-next-line no-undef +describe('test start bucket manager', function () { + var accessKey = proc.env.QINIU_ACCESS_KEY; + var secretKey = proc.env.QINIU_SECRET_KEY; + var srcBucket = proc.env.QINIU_TEST_BUCKET; + var domain = proc.env.QINIU_TEST_DOMAIN; + var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); + var config = new qiniu.conf.Config(); + // config.useHttpsDomain = true; + config.zone = qiniu.zone.Zone_z0; + var bucketManager = new qiniu.rs.BucketManager(mac, config); + // test stat + // eslint-disable-next-line no-undef + describe('test stat', function () { + // eslint-disable-next-line no-undef + it('test stat', function (done) { + var bucket = srcBucket; + var key = 'qiniu.mp4'; + bucketManager.stat(bucket, key, function (err, respBody, + respInfo) { + console.log(respBody, respInfo); + should.not.exist(err); + respBody.should.have.keys('hash', 'fsize', 'mimeType', + 'putTime', 'type'); + done(); + }); + }); + }); + + describe('test privateDownloadUrl', function () { + it('test privateDownloadUrl', function (done) { + var key = 'test_file'; + var url = bucketManager.privateDownloadUrl('http://' + domain, key, 20); + urllib.request(url, function (err, respBody, respInfo) { + console.log(respBody.toString(), respInfo); + should.not.exist(err); + should.equal(respInfo.status, 200); + done(); + }); + }); + }); + + // test copy and move and delete + // eslint-disable-next-line no-undef + describe('test copy', function () { + // eslint-disable-next-line no-undef + it('test copy', function (done) { + var destBucket = srcBucket; + var srcKey = 'qiniu.mp4'; + var destKey = 'qiniu_copy.mp4'; + var options = { + force: true + }; + bucketManager.copy(srcBucket, srcKey, destBucket, destKey, + options, + function (err, respBody, respInfo) { + // console.log(respBody); + should.not.exist(err); + assert.strictEqual(respInfo.statusCode, 200); + done(); + + // test move + // eslint-disable-next-line no-undef + describe('test move', function () { + var moveDestKey = 'qiniu_move.mp4'; + // eslint-disable-next-line no-undef + it('test move', function (done1) { + bucketManager.move(destBucket, destKey, + destBucket, moveDestKey, options, + function (err1, ret1, info1) { + should.not.exist(err1); + assert.strictEqual(info1.statusCode, 200); + done1(); + + // test delete + // eslint-disable-next-line no-undef + describe('test delete', function () { + // eslint-disable-next-line no-undef + it('test delete', function ( + done2) { + bucketManager.delete( + destBucket, + moveDestKey, + function (err2, ret2, + info2) { + should.not.exist( + err2); + assert.strictEqual(info2.statusCode, + 200); + done2(); + }); + }); + }); + }); + }); + }); + }); + }); + }); + + // test copy and deleteAfterDays + describe('test copy', function () { + it('test copy', function (done) { + var destBucket = srcBucket; + var srcKey = 'qiniu.mp4'; + var destKey = 'qiniu_delete_after_days.mp4'; + var options = { + force: true + }; + bucketManager.copy(srcBucket, srcKey, destBucket, destKey, options, + function (err, respBody, respInfo) { + // console.log(respBody); + should.not.exist(err); + assert.strictEqual(respInfo.statusCode, 200); + done(); + + // test deleteAfterDays + describe('test deleteAfterDays', function () { + it('test deleteAfterDays', function (done1) { + bucketManager.deleteAfterDays(destBucket, destKey, 1, + function (err1, ret1, info1) { + should.not.exist(err1); + assert.strictEqual(info1.statusCode, 200); + done1(); + }); }); }); - }); + }); + }); + }); + + // eslint-disable-next-line no-undef + describe('test fetch', function () { + // eslint-disable-next-line no-undef + it('test fetch', function (done) { + var resUrl = 'http://devtools.qiniu.com/qiniu.png'; + var bucket = srcBucket; + var key = 'qiniu.png'; + + bucketManager.fetch(resUrl, bucket, key, function (err, + respBody) { + should.not.exist(err); + respBody.should.have.keys('hash', 'fsize', 'mimeType', + 'key'); + done(); + }); + }); + }); + + // eslint-disable-next-line no-undef + describe('test changeMime', function () { + // eslint-disable-next-line no-undef + it('test changeMime', function (done) { + var key = 'test_file'; + var bucket = srcBucket; + + bucketManager.changeMime(bucket, key, 'text/html', + function (err, respBody, respInfo) { + should.not.exist(err); + assert.strictEqual(respInfo.statusCode, 200); + done(); + } + ); + }); + }); + + // eslint-disable-next-line no-undef + describe('test changeHeaders', function () { + // eslint-disable-next-line no-undef + it('test changeHeaders', function (done) { + var key = 'test_file'; + var bucket = srcBucket; + + bucketManager.changeHeaders(bucket, key, { + 'Content-Type': 'text/plain', + 'Last-Modified': 'Wed, 21 Oct 2015 07:28:00 GMT', + 'x-qn-test-custom-header': '0' + }, function (err, respBody, respInfo) { + console.log(respInfo); + should.not.exist(err); + assert.strictEqual(respInfo.statusCode, 200); + done(); + }); + }); + }); + + // stat file and changeType + describe('test changeType', function () { + it('test changeType', function (done) { + var key = 'test_file'; + var bucket = srcBucket; + bucketManager.stat(bucket, key, function (e, res, info) { + should.not.exist(e); + assert.strictEqual(info.statusCode, 200); + var type = res.type === 1 ? 0 : 1; + bucketManager.changeType(bucket, key, type, + function (err, respBody, respInfo) { + should.not.exist(err); + assert.strictEqual(respInfo.statusCode, 200); + done(); + } + ); + }); + }); + }); + + describe('test updateObjectStatus', function () { + it('test updateObjectStatus disable', function (done) { + var key = 'test_file'; + var bucket = srcBucket; + bucketManager.updateObjectStatus(bucket, key, 1, function (err, respBody, respInfo) { + should.not.exist(err); + assert.strictEqual(respInfo.statusCode, 200); + done(); + }); + }); + + it('test updateObjectStatus enable', function (done) { + var key = 'test_file'; + var bucket = srcBucket; + bucketManager.updateObjectStatus(bucket, key, 0, function (err, respBody, respInfo) { + should.not.exist(err); + assert.strictEqual(respInfo.statusCode, 200); + done(); + }); + }); + }); + + describe('test listBucket', function () { + it('test listBucket', function (done) { + bucketManager.listBucket(function (err, + respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + respBody.should.containEql(srcBucket); + done(); + }); + }); + }); + + // eslint-disable-next-line no-undef + describe('test bucketinfo', function () { + // eslint-disable-next-line no-undef + it('test bucketinfo', function (done) { + var bucket = srcBucket; + + bucketManager.getBucketInfo(bucket, function (err, + respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test listPrefix', function () { + it('test listPrefix', function (done) { + var bucket = srcBucket; + + bucketManager.listPrefix(bucket, { + prefix: 'test' + }, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + respBody.should.have.keys('items'); + respBody.items.forEach(function (item) { + item.should.have.keys('key', 'hash'); + item.key.should.startWith('test'); + }); + done(); + }); + }); + }); + + describe('test listPrefixV2', function () { + it('test listPrefixV2', function (done) { + var bucket = srcBucket; + + bucketManager.listPrefixV2(bucket, { + prefix: 'test' + }, function (err, respBody, respInfo) { + // the irregular data return from Server that Cannot be converted by urllib to JSON Object + // so err !=null and you can judge respBody==null or err.res.statusCode==200 + console.log(respBody + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + // eslint-disable-next-line no-undef + // 空间生命周期 + describe('test lifeRule', function () { + var bucket = srcBucket; + // add + describe('test putLifeRule', function () { + it('test putLifeRule', function (done) { + var options = { + name: 'hello', + prefix: 'test' + }; + bucketManager.putBucketLifecycleRule(bucket, options, function (err, + respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + // delete + describe('test deleteLifeRule', function () { + it('test deleteLifeRule', function (done) { + bucketManager.deleteBucketLifecycleRule(bucket, 'hello', function (err, + respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + // update + describe('test updateLifeRule', function () { + var options = { + name: 'hello', + history_to_line_after_days: 10, + delete_after_days: 10, + to_line_after_days: 8 + }; + it('test updateLifeRule', function (done) { + bucketManager.updateBucketLifecycleRule(bucket, options, function (err, + respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + // get + describe('test getLifeRule', function () { + it('test getLifeRule', function (done) { + bucketManager.getBucketLifecycleRule(bucket, function (err, + respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + }); + + describe('test events', function () { + var bucket = srcBucket; + describe('test addEvents', function () { + it('test addEvents', function (done) { + var options = { + name: 'event_testt', + event: 'mkfile', + callbackURL: 'http://node.ijemy.com/qncback' + }; + bucketManager.putBucketEvent(bucket, options, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test updateEvents', function () { + it('test updateEvents', function (done) { + var options = { + name: 'event_testt', + event: 'copy', + callbackURL: 'http://node.ijemy.com/qncback' + }; + bucketManager.updateBucketEvent(bucket, options, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test getEvents', function () { + it('test getEvents', function (done) { + bucketManager.getBucketEvent(bucket, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test deleteEvents', function () { + it('test deleteEvents', function (done) { + bucketManager.deleteBucketEvent(bucket, 'event_test', function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + }); + + describe('test referAntiLeech', function () { + describe('test referAntiLeech', function () { + var options = { + mode: 1, + norefer: 0, + pattern: '*.iorange.vip' + }; + var bucket = srcBucket; + it('test referAntiLeech', function (done) { + bucketManager.putReferAntiLeech(bucket, options, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); }); }); - }); }); }); - }); - describe('test fetch', function() { - it('test fetch', function(done) { - var resUrl = 'http://devtools.qiniu.com/qiniu.png'; - var bucket = srcBucket; - var key = "qiniu.png"; + describe('test corsRules', function () { + var bucket = srcBucket; + describe('test putCorsRules', function () { + it('test putCorsRules', function (done) { + var body = []; + var req01 = { + allowed_origin: ['http://www.test1.com'], + allowed_method: ['GET', 'POST'] + }; + var req02 = { + allowed_origin: ['http://www.test2.com'], + allowed_method: ['GET', 'POST', 'HEAD'], + allowed_header: ['testheader', 'Content-Type'], + exposed_header: ['test1', 'test2'], + max_age: 20 + }; + body[0] = req01; + body[1] = req02; - bucketManager.fetch(resUrl, bucket, key, function(err, - respBody, - respInfo) { - should.not.exist(err); - respBody.should.have.keys('hash', 'fsize', 'mimeType', - 'key'); - done(); - }); + bucketManager.putCorsRules(bucket, body, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test getCorsRules', function () { + it('test getCorsRules', function (done) { + bucketManager.getCorsRules(bucket, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + }); + // + // describe('test mirrorConfig', function() { + // describe('test getMirrorConfig', function() { + // var bucket = srcBucket; + // it('test getMirrorConfig', function(done) { + // var body = { + // "bucket":bucket, + // }; + // bucketManager.getBucketSourceConfig(body, function(err, respBody, respInfo) { + // should.not.exist(err); + // console.log(JSON.stringify(respBody) + "\n"); + // console.log(JSON.stringify(respInfo)); + // done(); + // }); + // }); + // }); + // }); + + describe('test accessMode', function () { + var bucket = srcBucket; + it('test accessMode', function (done) { + var mode = 0; + bucketManager.putBucketAccessStyleMode(bucket, mode, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test putBucketMaxAge', function () { + var bucket = srcBucket; + it('test putBucketMaxAge', function (done) { + var options = { + maxAge: 0 + }; + bucketManager.putBucketMaxAge(bucket, options, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test putBucketAccessMode', function () { + var bucket = srcBucket; + it('test putBucketAccessMode', function (done) { + var options = { + private: 0 + }; + bucketManager.putBucketAccessMode(bucket, options, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + + describe('test bucketQuota', function () { + var bucket = srcBucket; + describe('test putBucketQuota', function () { + it('test putBucketQuota', function (done) { + var options = { + size: 10, + count: 10 + }; + bucketManager.putBucketQuota(bucket, options, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + it('test cancel putBucketQuota', function (done) { + var options = { + size: -1, + count: -1 + }; + bucketManager.putBucketQuota(bucket, options, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + describe('test getBucketQuota', function () { + it('test getBucketQuota', function (done) { + bucketManager.getBucketQuota(bucket, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); + }); + }); + + describe('test listBucketDomains', function () { + var bucket = srcBucket; + it('test listBucketDomains', function (done) { + bucketManager.listBucketDomains(bucket, function (err, respBody, respInfo) { + should.not.exist(err); + console.log(JSON.stringify(respBody) + '\n'); + console.log(JSON.stringify(respInfo)); + done(); + }); + }); }); - }); }); diff --git a/test/rtc.test.js b/test/rtc.test.js new file mode 100644 index 00000000..7a3e9d71 --- /dev/null +++ b/test/rtc.test.js @@ -0,0 +1,80 @@ +const should = require('should'); +const assert = require('assert'); +const qiniu = require('../index.js'); +const proc = require('process'); +const console = require('console'); + +// eslint-disable-next-line no-undef +before(function (done) { + if (!process.env.QINIU_PILI_ACCESS_KEY || !process.env.QINIU_PILI_SECRET_KEY) { + console.log('should run command `source test-env.sh` first\n'); + process.exit(0); + } + done(); +}); + +// eslint-disable-next-line no-undef +describe('test rtc credentials', function () { + var accessKey = proc.env.QINIU_ACCESS_KEY; + var secretKey = proc.env.QINIU_SECRET_KEY; + + var credentials = new qiniu.Credentials(accessKey, secretKey); + var appId = null; + var appData = { + hub: 'sdk-live', + title: 'testtitle', + maxUsers: 10, + noAutoKickUser: true + }; + // eslint-disable-next-line no-undef + describe('test create app', function () { + // eslint-disable-next-line no-undef + it('create app', function (done) { + qiniu.app.createApp(appData, credentials, function (err, res) { + should.not.exist(err); + should.exist(res.appId); + assert.strictEqual(res.title, 'testtitle'); + appId = res.appId; + done(); + }); + }); + }); + + // eslint-disable-next-line no-undef + describe('test update app', function () { + // eslint-disable-next-line no-undef + it('update app', function (done) { + appData.title = 'testtitle2'; + qiniu.app.updateApp(appId, appData, credentials, function (err, res) { + should.not.exist(err); + assert.strictEqual(res.title, 'testtitle2'); + assert.strictEqual(res.appId, appId); + done(); + }); + }); + }); + + // eslint-disable-next-line no-undef + describe('test get app', function () { + // eslint-disable-next-line no-undef + it('get app', function (done) { + qiniu.app.getApp(appId, credentials, function (err, res) { + should.not.exist(err); + assert.strictEqual(res.title, 'testtitle2'); + assert.strictEqual(res.appId, appId); + done(); + }); + }); + }); + + // eslint-disable-next-line no-undef + describe('test delete app', function () { + // eslint-disable-next-line no-undef + it('delete app', function (done) { + qiniu.app.deleteApp(appId, credentials, function (err) { + should.not.exist(err); + done(); + }); + }); + }); +}); diff --git a/test/util.test.js b/test/util.test.js new file mode 100644 index 00000000..35a2958d --- /dev/null +++ b/test/util.test.js @@ -0,0 +1,77 @@ +const should = require('should'); +const qiniu = require('../index.js'); +const proc = require('process'); +const console = require('console'); + +// eslint-disable-next-line no-undef +before(function (done) { + if (!process.env.QINIU_ACCESS_KEY || !process.env.QINIU_SECRET_KEY || !process.env.QINIU_TEST_BUCKET || !process.env.QINIU_TEST_DOMAIN) { + console.log('should run command `source test-env.sh` first\n'); + process.exit(0); + } + done(); +}); + +describe('test util functions', function () { + var accessKey = proc.env.QINIU_ACCESS_KEY; + var secretKey = proc.env.QINIU_SECRET_KEY; + var bucket = proc.env.QINIU_TEST_BUCKET; + var mac = new qiniu.auth.digest.Mac(accessKey, secretKey); + var config = new qiniu.conf.Config(); + var bucketManager = new qiniu.rs.BucketManager(mac, config); + + describe('test prepareZone', function () { + it('test prepareZone', function (done) { + config.zone = qiniu.zone.Zone_z0; + qiniu.util.prepareZone(bucketManager, bucketManager.mac.accessKey, bucket, function (err, ctx) { + should.not.exist(err); + should.equal(bucketManager, ctx); + done(); + }); + }); + + it('test prepareZone error', function (done) { + config.zone = null; + qiniu.util.prepareZone(bucketManager, 'no_ak', 'no_bucket', function (err, ctx) { + should.exist(err); + done(); + }); + }); + + it('test prepareZone with null', function (done) { + config.zone = null; + qiniu.util.prepareZone(bucketManager, bucketManager.mac.accessKey, bucket, function (err, ctx) { + should.not.exist(err); + should.equal(bucketManager, ctx); + done(); + }); + }); + + it('test prepareZone with zone expired', function (done) { + config.zoneExpire = -1; + qiniu.util.prepareZone(bucketManager, bucketManager.mac.accessKey, bucket, function (err, ctx) { + should.not.exist(err); + should.equal(bucketManager, ctx); + done(); + }); + }); + + it('test prepareZone with zone expired', function (done) { + config.zoneExpire = parseInt(Date.now() / 1000) - 10; + qiniu.util.prepareZone(bucketManager, bucketManager.mac.accessKey, bucket, function (err, ctx) { + should.not.exist(err); + should.equal(bucketManager, ctx); + done(); + }); + }); + + it('test prepareZone with zone not expired', function (done) { + config.zoneExpire = parseInt(Date.now() / 1000) + 10; + qiniu.util.prepareZone(bucketManager, bucketManager.mac.accessKey, bucket, function (err, ctx) { + should.not.exist(err); + should.equal(bucketManager, ctx); + done(); + }); + }); + }); +});