Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to v8.6.0 #264

Merged
merged 5 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
**2024-09-05**

v8.6.0

新增:验证 Qbox, Qiniu 签名的辅助方法

新增:持久化处理,支持闲时任务

更改:对象存储,默认空间管理域名,查询区域主备域名

**2024-08-23**

v8.5.1
Expand Down
2 changes: 1 addition & 1 deletion src/Qiniu/Qiniu.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<PostBuildEvent>
</PostBuildEvent>
<ProjectId>Qiniu</ProjectId>
<Version>8.5.1</Version>
<Version>8.6.0</Version>
<Authors>Rong Zhou, Qiniu SDK</Authors>
<Company>Shanghai Qiniu Information Technology Co., Ltd.</Company>
<Description>Qiniu Resource (Cloud) Storage SDK for C#</Description>
Expand Down
2 changes: 1 addition & 1 deletion src/Qiniu/QiniuCSharpSDK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ public class QiniuCSharpSDK
/// <summary>
/// SDK版本号
/// </summary>
public const string VERSION = "8.5.1";
public const string VERSION = "8.6.0";

}
8 changes: 4 additions & 4 deletions src/Qiniu/Storage/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ public class Config
/// <summary>
/// 默认空间管理域名
/// </summary>
public static string DefaultUcHost = "uc.qbox.me";
public static string DefaultUcHost = "uc.qiniuapi.com";
/// <summary>
/// 默认查询区域域名
/// </summary>
public static string DefaultQueryRegionHost = "kodo-config.qiniuapi.com";
public static string DefaultQueryRegionHost = "uc.qiniuapi.com";
/// <summary>
/// 默认备用查询区域域名
/// </summary>
public static List<string> DefaultBackupQueryRegionHosts = new List<string>
{
"uc.qbox.me",
"api.qiniu.com"
"kodo-config.qiniuapi.com",
"uc.qbox.me"
};

/// <summary>
Expand Down
15 changes: 14 additions & 1 deletion src/Qiniu/Storage/OperationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,17 @@ public OperationManager(Mac mac, Config config)
/// <param name="pipeline">私有队列</param>
/// <param name="notifyUrl">通知url</param>
/// <param name="force">forece参数</param>
/// <param name="persistentType">为 1 时开启闲时任务</param>
/// <returns>pfop操作返回结果,正确返回结果包含persistentId</returns>
public PfopResult Pfop(string bucket, string key, string fops, string pipeline, string notifyUrl, bool force)
public PfopResult Pfop(
string bucket,
string key,
string fops,
string pipeline,
string notifyUrl,
bool force,
int type = 0
)
{
PfopResult result = new PfopResult();

Expand All @@ -65,6 +74,10 @@ public PfopResult Pfop(string bucket, string key, string fops, string pipeline,
{
sb.AppendFormat("&pipeline={0}", pipeline);
}
if (type > 0)
{
sb.AppendFormat("&type={0}", type);
}
byte[] data = Encoding.UTF8.GetBytes(sb.ToString());
string token = auth.CreateManageToken(pfopUrl, data);

Expand Down
10 changes: 10 additions & 0 deletions src/Qiniu/Storage/PfopInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ public class PfopInfo
[JsonProperty("id")]
public string Id;
/// <summary>
/// 任务类型,为 1 代表为闲时任务
/// </summary>
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
public int? Type;
/// <summary>
/// 任务创建时间
/// </summary>
[JsonProperty("creationDate", NullValueHandling = NullValueHandling.Ignore)]
public string CreationDate;
/// <summary>
/// 任务结果状态码
/// </summary>
[JsonProperty("code")]
Expand Down
2 changes: 1 addition & 1 deletion src/Qiniu/Storage/PrefopResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public PfopInfo Result

if ((Code == (int)HttpCode.OK) && (!string.IsNullOrEmpty(Text)))
{
info= JsonConvert.DeserializeObject<PfopInfo>(Text);
info= JsonConvert.DeserializeObject<PfopInfo>(Text);
}
return info;
}
Expand Down
7 changes: 7 additions & 0 deletions src/Qiniu/Storage/PutPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ public class PutPolicy
[JsonProperty("persistentPipeline", NullValueHandling = NullValueHandling.Ignore)]
public string PersistentPipeline { get; set; }

/// <summary>
/// [可选]持久化任务类型,为 1 时开启闲时任务
/// </summary>
[JsonProperty("persistentType", NullValueHandling = NullValueHandling.Ignore)]
public int? PersistentType { get; set; }


/// <summary>
/// [可选]上传文件大小限制:最小值,单位Byte
/// </summary>
Expand Down
45 changes: 45 additions & 0 deletions src/Qiniu/Util/Signature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,5 +200,50 @@ public string SignRequestV2(string method, string url, StringDictionary headers,
{
return SignRequestV2(method, url, headers, Encoding.UTF8.GetString(body));
}

public bool VerifyRequest(
string method,
string url,
StringDictionary headers,
string body = null
)
{
byte[] bodyBytes = null;
if (!string.IsNullOrEmpty(body)) {
bodyBytes = Encoding.UTF8.GetBytes(body);
}
return VerifyRequest(
method,
url,
headers,
bodyBytes
);
}

public bool VerifyRequest(
string method,
string url,
StringDictionary headers,
byte[] body = null
)
{
if (!headers.ContainsKey("Authorization"))
{
return false;
}

string authString = headers["Authorization"];
if (authString.StartsWith("QBox "))
{
return authString == "QBox " + SignRequest(url, body);
}

if (authString.StartsWith("Qiniu "))
{
return authString == "Qiniu " + SignRequestV2(method, url, headers, body);
}

return false;
}
}
}
4 changes: 2 additions & 2 deletions src/QiniuTests/Storage/ConfigTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ public void UcHostTest()
{
Config config = new Config();
string ucHost = config.UcHost();
Assert.AreEqual("http://uc.qbox.me", ucHost);
Assert.AreEqual("http://uc.qiniuapi.com", ucHost);
config.SetUcHost("uc.example.com");
ucHost = config.UcHost();
Assert.AreEqual("http://uc.example.com", ucHost);

config = new Config();
config.UseHttps = true;
ucHost = config.UcHost();
Assert.AreEqual("https://uc.qbox.me", ucHost);
Assert.AreEqual("https://uc.qiniuapi.com", ucHost);
config.SetUcHost("uc.example.com");
ucHost = config.UcHost();
Assert.AreEqual("https://uc.example.com", ucHost);
Expand Down
51 changes: 51 additions & 0 deletions src/QiniuTests/Storage/FormUploaderTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using NUnit.Framework;
using Qiniu.Http;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Qiniu.Util;
using Qiniu.Tests;

Expand Down Expand Up @@ -80,5 +82,54 @@ public void UploadFileV2Test()
System.IO.File.Delete(filePath);
}

[Test]
public void UploadFileWithPersistTypeTest()
{
Mac mac = new Mac(AccessKey, SecretKey);
Random rand = new Random();
string key = string.Format("UploadFileTest_{0}.dat", rand.Next());

string tempPath = System.IO.Path.GetTempPath();
int rnd = new Random().Next(1, 100000);
string filePath = tempPath + "resumeFile" + rnd.ToString();
char[] testBody = new char[4 * 1024 * 1024];
System.IO.FileStream stream = new System.IO.FileStream(filePath, System.IO.FileMode.Create);
System.IO.StreamWriter sw = new System.IO.StreamWriter(stream, System.Text.Encoding.Default);
sw.Write(testBody);
sw.Close();
stream.Close();

PutPolicy putPolicy = new PutPolicy();
putPolicy.Scope = Bucket + ":" + key;
putPolicy.SetExpires(3600);
putPolicy.DeleteAfterDays = 1;
string saveEntry = Base64.UrlSafeBase64Encode(Bucket + ":pfop-test_avinfo");
putPolicy.PersistentOps = "avinfo|saveas/" + saveEntry;
putPolicy.PersistentType = 1;
string token = Auth.CreateUploadToken(mac, putPolicy.ToJsonString());
Config config = new Config();
config.Zone = Zone.ZONE_CN_East;
config.UseHttps = true;
config.UseCdnDomains = true;
FormUploader target = new FormUploader(config);
PutExtra extra = new PutExtra();
extra.Version = "v2";
HttpResult result = target.UploadFile(filePath, key, token, extra);
Console.WriteLine("form upload result: " + result.ToString());
Assert.AreEqual((int)HttpCode.OK, result.Code);
System.IO.File.Delete(filePath);

Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(result.Text.ToString());
Assert.IsTrue(dict.ContainsKey("persistentId"));
OperationManager manager = new OperationManager(mac, config);
PrefopResult prefopRet = manager.Prefop(dict["persistentId"].ToString());
if (prefopRet.Code != (int)HttpCode.OK)
{
Assert.Fail("prefop error: " + prefopRet.ToString());
}
Assert.AreEqual(1, prefopRet.Result.Type);
Assert.IsNotNull(prefopRet.Result.CreationDate);
Assert.IsNotEmpty(prefopRet.Result.CreationDate);
}
}
}
52 changes: 43 additions & 9 deletions src/QiniuTests/Storage/OperationManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,30 @@ namespace Qiniu.Storage.Tests
[TestFixture]
public class OperationManagerTests :TestEnv
{
private OperationManager getOperationManager()
{
Mac mac = new Mac(AccessKey, SecretKey);
Config config = new Config();
// config.UseHttps = true;

OperationManager manager = new OperationManager(mac, config);
return manager;
}

[Test]
public void PfopTest()
public void PfopAndPrefopTest()
{
string key = "qiniu.mp4";
bool force = true;
string pipeline = "sdktest";
string notifyUrl = "http://api.example.com/qiniu/pfop/notify";
string saveMp4Entry = Base64.UrlSafeBase64Encode(Bucket + ":avthumb_test_target.mp4");
string saveJpgEntry = Base64.UrlSafeBase64Encode(Bucket + ":vframe_test_target.jpg");
string avthumbMp4Fop = "avthumb/mp4|saveas/" + saveMp4Entry;
string vframeJpgFop = "vframe/jpg/offset/1|saveas/" + saveJpgEntry;
string fops = string.Join(";", new string[] { avthumbMp4Fop, vframeJpgFop });
Mac mac = new Mac(AccessKey, SecretKey);
Config config = new Config();
config.UseHttps = true;
OperationManager manager = new OperationManager(mac, config);
string pipeline = "sdktest";
string notifyUrl = "http://api.example.com/qiniu/pfop/notify";
string key = "qiniu.mp4";
bool force = true;

OperationManager manager = getOperationManager();
PfopResult pfopRet = manager.Pfop(Bucket, key, fops, pipeline, notifyUrl, force);
if (pfopRet.Code != (int)HttpCode.OK)
{
Expand All @@ -42,5 +49,32 @@ public void PfopTest()
}
Console.WriteLine(ret.ToString());
}

[Test]
public void PfopWithIdleTimeTest()
{
string key = "qiniu.mp4";
bool force = true;
int type = 1;
string pipeline = null;
string saveJpgEntry = Base64.UrlSafeBase64Encode(Bucket + ":vframe_test_target.jpg");
string vframeJpgFop = "vframe/jpg/offset/1|saveas/" + saveJpgEntry;

OperationManager manager = getOperationManager();
PfopResult pfopRet = manager.Pfop(Bucket, key, vframeJpgFop, pipeline, null, force, type);
if (pfopRet.Code != (int)HttpCode.OK)
{
Assert.Fail("pfop error: " + pfopRet.ToString());
}

PrefopResult prefopRet = manager.Prefop(pfopRet.PersistentId);
if (prefopRet.Code != (int)HttpCode.OK)
{
Assert.Fail("prefop error: " + prefopRet.ToString());
}
Assert.AreEqual(1, prefopRet.Result.Type);
Assert.IsNotNull(prefopRet.Result.CreationDate);
Assert.IsNotEmpty(prefopRet.Result.CreationDate);
}
}
}
8 changes: 8 additions & 0 deletions src/QiniuTests/Util/Signature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,13 @@ public string SignatureV2ByBytesTest(string method, string url, StringDictionary
{
return string.Format("Qiniu {0}", sign.SignRequestV2(method, url, headers, Encoding.UTF8.GetBytes(body)));
}

[TestCaseSource(typeof(VerifyRequestDataClass), nameof(VerifyRequestDataClass.TestCases))]
public bool VerifyRequestTest(string method, string url, StringDictionary headers, string body)
{
Mac mac = new Mac("abcdefghklmnopq", "1234567890");
Signature mockSign = new Signature(mac);
return mockSign.VerifyRequest(method, url, headers, body);
}
}
}
34 changes: 33 additions & 1 deletion src/QiniuTests/Util/TestCases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,4 +211,36 @@ public static IEnumerable TestCases
}
}
}
}

public class VerifyRequestDataClass
{
public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(
"",
"https://test.qiniu.com/callback",
new StringDictionary
{
{"Authorization", "QBox abcdefghklmnopq:T7F-SjxX7X2zI4Fc1vANiNt1AUE="},
{"Content-Type", "application/x-www-form-urlencoded"}
},
"name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm-RlQx_4O2&location=Shanghai&price=1500.00&uid=123"
).Returns(true);

yield return new TestCaseData(
"GET",
"https://test.qiniu.com/callback",
new StringDictionary
{
{"Authorization", "Qiniu abcdefghklmnopq:ZqS7EZuAKrhZaEIxqNGxDJi41IQ="},
{"X-Qiniu-Bbb", "BBB"},
{"Content-Type", "application/x-www-form-urlencoded"}
},
"name=sunflower.jpg&hash=Fn6qeQi4VDLQ347NiRm-RlQx_4O2&location=Shanghai&price=1500.00&uid=123"
).Returns(true);
}
}
}
}
Loading