chore: 重构了 AVCommand 及 http 模块
parent
c6bbf3219f
commit
ca3b19311c
|
|
@ -10,6 +10,7 @@ namespace LeanCloudTests {
|
||||||
AVClient.Initialize(new AVClient.Configuration {
|
AVClient.Initialize(new AVClient.Configuration {
|
||||||
ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz",
|
ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz",
|
||||||
ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp",
|
ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp",
|
||||||
|
ApiServer = "https://avoscloud.com"
|
||||||
});
|
});
|
||||||
AVClient.HttpLog(TestContext.Out.WriteLine);
|
AVClient.HttpLog(TestContext.Out.WriteLine);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using LeanCloud;
|
||||||
|
|
||||||
|
namespace LeanCloudTests {
|
||||||
|
public class QueryTest {
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp() {
|
||||||
|
AVClient.Initialize(new AVClient.Configuration {
|
||||||
|
ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz",
|
||||||
|
ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp",
|
||||||
|
RTMServer = "https://router-g0-push.avoscloud.com",
|
||||||
|
});
|
||||||
|
AVClient.HttpLog(TestContext.Out.WriteLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TestQuery() {
|
||||||
|
var query = new AVQuery<AVObject>("Foo");
|
||||||
|
query.WhereEqualTo("content", "hello, world");
|
||||||
|
var count = await query.CountAsync();
|
||||||
|
Assert.Greater(count, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Utilities;
|
using LeanCloud.Utilities;
|
||||||
using LeanCloud.Storage.Internal;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
namespace LeanCloud.Storage.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -21,11 +21,11 @@ namespace LeanCloud.Storage.Internal
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand(string.Format("functions/{0}", Uri.EscapeUriString(name)),
|
var command = new EngineCommand {
|
||||||
method: "POST",
|
Path = $"functions/{Uri.EscapeUriString(name)}",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: NoObjectsEncoder.Instance.Encode(parameters) as IDictionary<string, object>);
|
Content = parameters
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
||||||
|
|
@ -39,11 +39,11 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
public Task<T> RPCFunction<T>(string name, IDictionary<string, object> parameters, string sessionToken, CancellationToken cancellationToken)
|
public Task<T> RPCFunction<T>(string name, IDictionary<string, object> parameters, string sessionToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand(string.Format("call/{0}", Uri.EscapeUriString(name)),
|
var command = new EngineCommand {
|
||||||
method: "POST",
|
Path = $"call/{Uri.EscapeUriString(name)}",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: PointerOrLocalIdEncoder.Instance.Encode(parameters) as IDictionary<string, object>);
|
Content = parameters
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
||||||
|
|
|
||||||
|
|
@ -12,158 +12,30 @@ namespace LeanCloud.Storage.Internal
|
||||||
/// AVCommand is an <see cref="HttpRequest"/> with pre-populated
|
/// AVCommand is an <see cref="HttpRequest"/> with pre-populated
|
||||||
/// headers.
|
/// headers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AVCommand : HttpRequest
|
public class AVCommand {
|
||||||
{
|
// 不同服务对应的服务器地址不同
|
||||||
public object Body {
|
public virtual string Server => AVClient.CurrentConfiguration.ApiServer;
|
||||||
|
|
||||||
|
public string Path {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Stream Data {
|
public HttpMethod Method {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<string, string> Headers {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Content {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri Uri {
|
||||||
get {
|
get {
|
||||||
return new MemoryStream(Encoding.UTF8.GetBytes(Json.Encode(Body)));
|
return new Uri($"{Server}/{AVClient.APIVersion}/{Path}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AVCommand(string relativeUri,
|
|
||||||
string method,
|
|
||||||
string sessionToken = null,
|
|
||||||
IList<KeyValuePair<string, string>> headers = null,
|
|
||||||
object data = null)
|
|
||||||
{
|
|
||||||
var state = AVPlugins.Instance.AppRouterController.Get();
|
|
||||||
var urlTemplate = "https://{0}/{1}/{2}";
|
|
||||||
AVClient.Configuration configuration = AVClient.CurrentConfiguration;
|
|
||||||
var apiVersion = "1.1";
|
|
||||||
if (relativeUri.StartsWith("push", StringComparison.Ordinal) ||
|
|
||||||
relativeUri.StartsWith("installations", StringComparison.Ordinal)) {
|
|
||||||
Uri = new Uri(string.Format(urlTemplate, state.PushServer, apiVersion, relativeUri));
|
|
||||||
if (configuration.PushServer != null) {
|
|
||||||
Uri = new Uri(string.Format("{0}{1}/{2}", configuration.PushServer, apiVersion, relativeUri));
|
|
||||||
}
|
|
||||||
} else if (relativeUri.StartsWith("stats", StringComparison.Ordinal) ||
|
|
||||||
relativeUri.StartsWith("always_collect", StringComparison.Ordinal) ||
|
|
||||||
relativeUri.StartsWith("statistics", StringComparison.Ordinal)) {
|
|
||||||
Uri = new Uri(string.Format(urlTemplate, state.StatsServer, apiVersion, relativeUri));
|
|
||||||
if (configuration.StatsServer != null) {
|
|
||||||
Uri = new Uri(string.Format("{0}{1}/{2}", configuration.StatsServer, apiVersion, relativeUri));
|
|
||||||
}
|
|
||||||
} else if (relativeUri.StartsWith("functions", StringComparison.Ordinal) ||
|
|
||||||
relativeUri.StartsWith("call", StringComparison.Ordinal)) {
|
|
||||||
Uri = new Uri(string.Format(urlTemplate, state.EngineServer, apiVersion, relativeUri));
|
|
||||||
|
|
||||||
if (configuration.EngineServer != null) {
|
|
||||||
Uri = new Uri(string.Format("{0}{1}/{2}", configuration.EngineServer, apiVersion, relativeUri));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Uri = new Uri(string.Format(urlTemplate, state.ApiServer, apiVersion, relativeUri));
|
|
||||||
|
|
||||||
if (configuration.ApiServer != null) {
|
|
||||||
Uri = new Uri(string.Format("{0}{1}/{2}", configuration.ApiServer, apiVersion, relativeUri));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switch (method) {
|
|
||||||
case "GET":
|
|
||||||
Method = HttpMethod.Get;
|
|
||||||
break;
|
|
||||||
case "POST":
|
|
||||||
Method = HttpMethod.Post;
|
|
||||||
break;
|
|
||||||
case "DELETE":
|
|
||||||
Method = HttpMethod.Delete;
|
|
||||||
break;
|
|
||||||
case "PUT":
|
|
||||||
Method = HttpMethod.Put;
|
|
||||||
break;
|
|
||||||
case "HEAD":
|
|
||||||
Method = HttpMethod.Head;
|
|
||||||
break;
|
|
||||||
case "TRACE":
|
|
||||||
Method = HttpMethod.Trace;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Body = data;
|
|
||||||
Headers = new List<KeyValuePair<string, string>>(headers ?? Enumerable.Empty<KeyValuePair<string, string>>());
|
|
||||||
|
|
||||||
string useProduction = AVClient.UseProduction ? "1" : "0";
|
|
||||||
Headers.Add(new KeyValuePair<string, string>("X-LC-Prod", useProduction));
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(sessionToken)) {
|
|
||||||
Headers.Add(new KeyValuePair<string, string>("X-LC-Session", sessionToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
Headers.Add(new KeyValuePair<string, string>("Content-Type", "application/json"));
|
|
||||||
}
|
|
||||||
|
|
||||||
//public AVCommand(string relativeUri,
|
|
||||||
// string method,
|
|
||||||
// string sessionToken = null,
|
|
||||||
// IList<KeyValuePair<string, string>> headers = null,
|
|
||||||
// Stream stream = null,
|
|
||||||
// string contentType = null)
|
|
||||||
//{
|
|
||||||
// var state = AVPlugins.Instance.AppRouterController.Get();
|
|
||||||
// var urlTemplate = "https://{0}/{1}/{2}";
|
|
||||||
// AVClient.Configuration configuration = AVClient.CurrentConfiguration;
|
|
||||||
// var apiVersion = "1.1";
|
|
||||||
// if (relativeUri.StartsWith("push") || relativeUri.StartsWith("installations"))
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format(urlTemplate, state.PushServer, apiVersion, relativeUri));
|
|
||||||
// if (configuration.PushServer != null)
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format("{0}{1}/{2}", configuration.PushServer, apiVersion, relativeUri));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if (relativeUri.StartsWith("stats") || relativeUri.StartsWith("always_collect") || relativeUri.StartsWith("statistics"))
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format(urlTemplate, state.StatsServer, apiVersion, relativeUri));
|
|
||||||
// if (configuration.StatsServer != null)
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format("{0}{1}/{2}", configuration.StatsServer, apiVersion, relativeUri));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else if (relativeUri.StartsWith("functions") || relativeUri.StartsWith("call"))
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format(urlTemplate, state.EngineServer, apiVersion, relativeUri));
|
|
||||||
|
|
||||||
// if (configuration.EngineServer != null)
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format("{0}{1}/{2}", configuration.EngineServer, apiVersion, relativeUri));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format(urlTemplate, state.ApiServer, apiVersion, relativeUri));
|
|
||||||
|
|
||||||
// if (configuration.ApiServer != null)
|
|
||||||
// {
|
|
||||||
// Uri = new Uri(string.Format("{0}{1}/{2}", configuration.ApiServer, apiVersion, relativeUri));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Method = method;
|
|
||||||
// Data = stream;
|
|
||||||
// Headers = new List<KeyValuePair<string, string>>(headers ?? Enumerable.Empty<KeyValuePair<string, string>>());
|
|
||||||
|
|
||||||
// string useProduction = AVClient.UseProduction ? "1" : "0";
|
|
||||||
// Headers.Add(new KeyValuePair<string, string>("X-LC-Prod", useProduction));
|
|
||||||
|
|
||||||
// if (!string.IsNullOrEmpty(sessionToken))
|
|
||||||
// {
|
|
||||||
// Headers.Add(new KeyValuePair<string, string>("X-LC-Session", sessionToken));
|
|
||||||
// }
|
|
||||||
// if (!string.IsNullOrEmpty(contentType))
|
|
||||||
// {
|
|
||||||
// Headers.Add(new KeyValuePair<string, string>("Content-Type", contentType));
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
public AVCommand(AVCommand other)
|
|
||||||
{
|
|
||||||
this.Uri = other.Uri;
|
|
||||||
this.Method = other.Method;
|
|
||||||
this.Headers = new List<KeyValuePair<string, string>>(other.Headers);
|
|
||||||
this.Body = other.Data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Storage.Internal;
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
namespace LeanCloud.Storage.Internal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Command Runner.
|
/// Command Runner.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AVCommandRunner : IAVCommandRunner
|
public class AVCommandRunner : IAVCommandRunner {
|
||||||
{
|
public const string APPLICATION_JSON = "application/json";
|
||||||
private readonly IHttpClient httpClient;
|
|
||||||
|
private readonly System.Net.Http.HttpClient httpClient;
|
||||||
private readonly IInstallationIdController installationIdController;
|
private readonly IInstallationIdController installationIdController;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -23,7 +26,7 @@ namespace LeanCloud.Storage.Internal
|
||||||
/// <param name="installationIdController"></param>
|
/// <param name="installationIdController"></param>
|
||||||
public AVCommandRunner(IHttpClient httpClient, IInstallationIdController installationIdController)
|
public AVCommandRunner(IHttpClient httpClient, IInstallationIdController installationIdController)
|
||||||
{
|
{
|
||||||
this.httpClient = httpClient;
|
this.httpClient = new System.Net.Http.HttpClient();
|
||||||
this.installationIdController = installationIdController;
|
this.installationIdController = installationIdController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,133 +38,113 @@ namespace LeanCloud.Storage.Internal
|
||||||
/// <param name="downloadProgress"></param>
|
/// <param name="downloadProgress"></param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(HttpRequest command,
|
public async Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command,
|
||||||
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
|
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
|
||||||
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
|
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken)) {
|
||||||
{
|
|
||||||
return PrepareCommand(command).ContinueWith(commandTask =>
|
var request = new HttpRequestMessage {
|
||||||
{
|
RequestUri = command.Uri,
|
||||||
var requestLog = commandTask.Result.ToLog();
|
Method = command.Method,
|
||||||
AVClient.PrintLog("http=>" + requestLog);
|
Content = new StringContent(Json.Encode(command.Content))
|
||||||
|
};
|
||||||
|
|
||||||
return httpClient.ExecuteAsync(commandTask.Result, uploadProgress, downloadProgress, cancellationToken).OnSuccess(t =>
|
var headers = await GetHeadersAsync();
|
||||||
{
|
foreach (var header in headers) {
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
if (!string.IsNullOrEmpty(header.Value)) {
|
||||||
|
request.Headers.Add(header.Key, header.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.Content.Headers.ContentType = new MediaTypeHeaderValue(APPLICATION_JSON);
|
||||||
|
|
||||||
var response = t.Result;
|
PrintRequest(command, headers);
|
||||||
var contentString = response.Item2;
|
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||||
int responseCode = (int)response.Item1;
|
request.Dispose();
|
||||||
|
|
||||||
var responseLog = responseCode + ";" + contentString;
|
var resultString = await response.Content.ReadAsStringAsync();
|
||||||
AVClient.PrintLog("http<=" + responseLog);
|
response.Dispose();
|
||||||
|
PrintResponse(response, resultString);
|
||||||
|
|
||||||
if (responseCode >= 500)
|
var ret = new Tuple<HttpStatusCode, string>(response.StatusCode, resultString);
|
||||||
{
|
|
||||||
// Server error, return InternalServerError.
|
var responseCode = ret.Item1;
|
||||||
throw new AVException(AVException.ErrorCode.InternalServerError, response.Item2);
|
var contentString = ret.Item2;
|
||||||
|
|
||||||
|
if (responseCode >= HttpStatusCode.InternalServerError) {
|
||||||
|
// Server error, return InternalServerError.
|
||||||
|
throw new AVException(AVException.ErrorCode.InternalServerError, contentString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentString != null) {
|
||||||
|
IDictionary<string, object> contentJson = null;
|
||||||
|
try {
|
||||||
|
if (contentString.StartsWith("[", StringComparison.Ordinal)) {
|
||||||
|
var arrayJson = Json.Parse(contentString);
|
||||||
|
contentJson = new Dictionary<string, object> { { "results", arrayJson } };
|
||||||
|
} else {
|
||||||
|
contentJson = Json.Parse(contentString) as IDictionary<string, object>;
|
||||||
}
|
}
|
||||||
else if (contentString != null)
|
} catch (Exception e) {
|
||||||
{
|
throw new AVException(AVException.ErrorCode.OtherCause,
|
||||||
IDictionary<string, object> contentJson = null;
|
"Invalid response from server", e);
|
||||||
try
|
}
|
||||||
{
|
if (responseCode < HttpStatusCode.OK || responseCode > HttpStatusCode.PartialContent) {
|
||||||
if (contentString.StartsWith("["))
|
AVClient.PrintLog("error response code:" + responseCode);
|
||||||
{
|
int code = (int)(contentJson.ContainsKey("code") ? (int)contentJson["code"] : (int)AVException.ErrorCode.OtherCause);
|
||||||
var arrayJson = Json.Parse(contentString);
|
string error = contentJson.ContainsKey("error") ?
|
||||||
contentJson = new Dictionary<string, object> { { "results", arrayJson } };
|
contentJson["error"] as string : contentString;
|
||||||
}
|
AVException.ErrorCode ec = (AVException.ErrorCode)code;
|
||||||
else
|
throw new AVException(ec, error);
|
||||||
{
|
}
|
||||||
contentJson = Json.Parse(contentString) as IDictionary<string, object>;
|
return new Tuple<HttpStatusCode, IDictionary<string, object>>(responseCode, contentJson);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception e)
|
return new Tuple<HttpStatusCode, IDictionary<string, object>>(responseCode, null);
|
||||||
{
|
|
||||||
throw new AVException(AVException.ErrorCode.OtherCause,
|
|
||||||
"Invalid response from server", e);
|
|
||||||
}
|
|
||||||
if (responseCode < 200 || responseCode > 299)
|
|
||||||
{
|
|
||||||
AVClient.PrintLog("error response code:" + responseCode);
|
|
||||||
int code = (int)(contentJson.ContainsKey("code") ? (int)contentJson["code"] : (int)AVException.ErrorCode.OtherCause);
|
|
||||||
string error = contentJson.ContainsKey("error") ?
|
|
||||||
contentJson["error"] as string : contentString;
|
|
||||||
AVException.ErrorCode ec = (AVException.ErrorCode)code;
|
|
||||||
throw new AVException(ec, error);
|
|
||||||
}
|
|
||||||
return new Tuple<HttpStatusCode, IDictionary<string, object>>(response.Item1,
|
|
||||||
contentJson);
|
|
||||||
}
|
|
||||||
return new Tuple<HttpStatusCode, IDictionary<string, object>>(response.Item1, null);
|
|
||||||
});
|
|
||||||
}).Unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private const string revocableSessionTokenTrueValue = "1";
|
private const string revocableSessionTokenTrueValue = "1";
|
||||||
private Task<HttpRequest> PrepareCommand(HttpRequest command)
|
|
||||||
{
|
|
||||||
HttpRequest newCommand = command;
|
|
||||||
|
|
||||||
Task<HttpRequest> installationIdTask = installationIdController.GetAsync().ContinueWith(t =>
|
|
||||||
{
|
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Installation-Id", t.Result.ToString()));
|
|
||||||
return newCommand;
|
|
||||||
});
|
|
||||||
|
|
||||||
AVClient.Configuration configuration = AVClient.CurrentConfiguration;
|
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Id", configuration.ApplicationId));
|
|
||||||
|
|
||||||
|
async Task<Dictionary<string, string>> GetHeadersAsync() {
|
||||||
|
var headers = new Dictionary<string, string>();
|
||||||
|
var installationId = await installationIdController.GetAsync();
|
||||||
|
headers.Add("X-LC-Installation-Id", installationId.ToString());
|
||||||
|
var conf = AVClient.CurrentConfiguration;
|
||||||
|
headers.Add("X-LC-Id", conf.ApplicationId);
|
||||||
long timestamp = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds;
|
long timestamp = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds;
|
||||||
if (!string.IsNullOrEmpty(configuration.MasterKey) && AVClient.UseMasterKey)
|
if (!string.IsNullOrEmpty(conf.MasterKey) && AVClient.UseMasterKey) {
|
||||||
{
|
string sign = MD5.GetMd5String(timestamp + conf.MasterKey);
|
||||||
string sign = MD5.GetMd5String(timestamp + configuration.MasterKey);
|
headers.Add("X-LC-Sign", $"{sign},{timestamp},master");
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Sign", string.Format("{0},{1},master", sign, timestamp)));
|
} else {
|
||||||
}
|
string sign = MD5.GetMd5String(timestamp + conf.ApplicationKey);
|
||||||
else
|
headers.Add("X-LC-Sign", $"{sign},{timestamp}");
|
||||||
{
|
|
||||||
string sign = MD5.GetMd5String(timestamp + configuration.ApplicationKey);
|
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Sign", string.Format("{0},{1}", sign, timestamp)));
|
|
||||||
}
|
}
|
||||||
|
// TODO 重新设计版本号
|
||||||
|
headers.Add("X-LC-Client-Version", AVClient.VersionString);
|
||||||
|
headers.Add("X-LC-App-Build-Version", conf.VersionInfo.BuildVersion);
|
||||||
|
headers.Add("X-LC-App-Display-Version", conf.VersionInfo.DisplayVersion);
|
||||||
|
headers.Add("X-LC-OS-Version", conf.VersionInfo.OSVersion);
|
||||||
|
headers.Add("X-LeanCloud-Revocable-Session", revocableSessionTokenTrueValue);
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Client-Version", AVClient.VersionString));
|
static void PrintRequest(AVCommand request, Dictionary<string, string> headers) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.AppendLine("=== HTTP Request Start ===");
|
||||||
|
sb.AppendLine($"URL: {request.Uri}");
|
||||||
|
sb.AppendLine($"Method: {request.Method}");
|
||||||
|
sb.AppendLine($"Headers: {JsonConvert.SerializeObject(headers)}");
|
||||||
|
sb.AppendLine($"Content: {JsonConvert.SerializeObject(request.Content)}");
|
||||||
|
sb.AppendLine("=== HTTP Request End ===");
|
||||||
|
AVClient.PrintLog(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(configuration.VersionInfo.BuildVersion))
|
static void PrintResponse(HttpResponseMessage response, string content) {
|
||||||
{
|
StringBuilder sb = new StringBuilder();
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-App-Build-Version", configuration.VersionInfo.BuildVersion));
|
sb.AppendLine("=== HTTP Response Start ===");
|
||||||
}
|
sb.AppendLine($"URL: {response.RequestMessage.RequestUri}");
|
||||||
if (!string.IsNullOrEmpty(configuration.VersionInfo.DisplayVersion))
|
sb.AppendLine($"Content: {content}");
|
||||||
{
|
sb.AppendLine("=== HTTP Response End ===");
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-App-Display-Version", configuration.VersionInfo.DisplayVersion));
|
AVClient.PrintLog(sb.ToString());
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(configuration.VersionInfo.OSVersion))
|
|
||||||
{
|
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-OS-Version", configuration.VersionInfo.OSVersion));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AVUser.IsRevocableSessionEnabled)
|
|
||||||
{
|
|
||||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LeanCloud-Revocable-Session", revocableSessionTokenTrueValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configuration.AdditionalHTTPHeaders != null)
|
|
||||||
{
|
|
||||||
var headersDictionary = newCommand.Headers.ToDictionary(kv => kv.Key, kv => kv.Value);
|
|
||||||
foreach (var header in configuration.AdditionalHTTPHeaders)
|
|
||||||
{
|
|
||||||
if (headersDictionary.ContainsKey(header.Key))
|
|
||||||
{
|
|
||||||
headersDictionary[header.Key] = header.Value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newCommand.Headers.Add(header);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newCommand.Headers = headersDictionary.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return installationIdTask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace LeanCloud.Storage.Internal {
|
||||||
|
public class EngineCommand : AVCommand {
|
||||||
|
public override string Server => AVClient.CurrentConfiguration.EngineServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ namespace LeanCloud.Storage.Internal
|
||||||
/// <param name="downloadProgress">Download progress callback.</param>
|
/// <param name="downloadProgress">Download progress callback.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token for the request.</param>
|
/// <param name="cancellationToken">The cancellation token for the request.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(HttpRequest command,
|
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command,
|
||||||
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
|
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
|
||||||
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
|
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken));
|
CancellationToken cancellationToken = default(CancellationToken));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
using LeanCloud;
|
||||||
|
|
||||||
|
namespace LeanCloud.Storage.Internal {
|
||||||
|
public class RTMCommand : AVCommand {
|
||||||
|
public override string Server => AVClient.CurrentConfiguration.RTMServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using LeanCloud.Storage.Internal;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -22,10 +22,10 @@ namespace LeanCloud.Storage.Internal {
|
||||||
public IAVCurrentConfigController CurrentConfigController { get; internal set; }
|
public IAVCurrentConfigController CurrentConfigController { get; internal set; }
|
||||||
|
|
||||||
public Task<AVConfig> FetchConfigAsync(String sessionToken, CancellationToken cancellationToken) {
|
public Task<AVConfig> FetchConfigAsync(String sessionToken, CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand("config",
|
var command = new AVCommand {
|
||||||
method: "GET",
|
Path = "config",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(task => {
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(task => {
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace LeanCloud.Storage.Internal
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AVFileController : IAVFileController
|
public class AVFileController : IAVFileController
|
||||||
{
|
{
|
||||||
private readonly IAVCommandRunner commandRunner;
|
protected readonly IAVCommandRunner commandRunner;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="T:LeanCloud.Storage.Internal.AVFileController"/> class.
|
/// Initializes a new instance of the <see cref="T:LeanCloud.Storage.Internal.AVFileController"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -66,14 +66,13 @@ namespace LeanCloud.Storage.Internal
|
||||||
}
|
}
|
||||||
public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken)
|
public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand("files/" + state.ObjectId,
|
var command = new AVCommand {
|
||||||
method: "DELETE",
|
Path = $"files/{state.ObjectId}",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Delete
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
internal static Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken)
|
internal Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> rtn;
|
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> rtn;
|
||||||
string currentSessionToken = AVUser.CurrentSessionToken;
|
string currentSessionToken = AVUser.CurrentSessionToken;
|
||||||
|
|
@ -85,17 +84,19 @@ namespace LeanCloud.Storage.Internal
|
||||||
parameters.Add("mime_type", AVFile.GetMIMEType(str));
|
parameters.Add("mime_type", AVFile.GetMIMEType(str));
|
||||||
parameters.Add("metaData", fileState.MetaData);
|
parameters.Add("metaData", fileState.MetaData);
|
||||||
|
|
||||||
rtn = AVClient.RequestAsync("POST", new Uri("fileTokens", UriKind.Relative), currentSessionToken, parameters, cancellationToken);
|
var command = new AVCommand {
|
||||||
|
Path = "fileTokens",
|
||||||
return rtn;
|
Method = HttpMethod.Post,
|
||||||
|
Content = parameters
|
||||||
|
};
|
||||||
|
return commandRunner.RunCommandAsync(command);
|
||||||
}
|
}
|
||||||
public Task<FileState> GetAsync(string objectId, string sessionToken, CancellationToken cancellationToken)
|
public Task<FileState> GetAsync(string objectId, string sessionToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand("files/" + objectId,
|
var command = new AVCommand {
|
||||||
method: "GET",
|
Path = $"files/{objectId}",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Get
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(_ =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(_ =>
|
||||||
{
|
{
|
||||||
var result = _.Result;
|
var result = _.Result;
|
||||||
|
|
|
||||||
|
|
@ -161,9 +161,12 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
parameters.Add("metaData", state.MetaData);
|
parameters.Add("metaData", state.MetaData);
|
||||||
|
|
||||||
rtn = AVClient.RequestAsync("POST", new Uri("qiniu", UriKind.Relative), currentSessionToken, parameters, cancellationToken);
|
var command = new AVCommand {
|
||||||
|
Path = "qiniu",
|
||||||
return rtn;
|
Method = HttpMethod.Post,
|
||||||
|
Content = parameters
|
||||||
|
};
|
||||||
|
return commandRunner.RunCommandAsync(command);
|
||||||
}
|
}
|
||||||
IList<KeyValuePair<string, string>> GetQiniuRequestHeaders(FileState state)
|
IList<KeyValuePair<string, string>> GetQiniuRequestHeaders(FileState state)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -4,32 +4,24 @@ using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Utilities;
|
using LeanCloud.Utilities;
|
||||||
using LeanCloud.Storage.Internal;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
namespace LeanCloud.Storage.Internal {
|
||||||
{
|
public class AVObjectController : IAVObjectController {
|
||||||
public class AVObjectController : IAVObjectController
|
|
||||||
{
|
|
||||||
private readonly IAVCommandRunner commandRunner;
|
private readonly IAVCommandRunner commandRunner;
|
||||||
|
|
||||||
public AVObjectController(IAVCommandRunner commandRunner)
|
public AVObjectController(IAVCommandRunner commandRunner) {
|
||||||
{
|
|
||||||
this.commandRunner = commandRunner;
|
this.commandRunner = commandRunner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IObjectState> FetchAsync(IObjectState state,
|
public Task<IObjectState> FetchAsync(IObjectState state,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
var command = new AVCommand {
|
||||||
var command = new AVCommand(string.Format("classes/{0}/{1}",
|
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}",
|
||||||
Uri.EscapeDataString(state.ClassName),
|
Method = HttpMethod.Get
|
||||||
Uri.EscapeDataString(state.ObjectId)),
|
};
|
||||||
method: "GET",
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||||
sessionToken: sessionToken,
|
|
||||||
data: null);
|
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
|
||||||
{
|
|
||||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -37,18 +29,12 @@ namespace LeanCloud.Storage.Internal
|
||||||
public Task<IObjectState> FetchAsync(IObjectState state,
|
public Task<IObjectState> FetchAsync(IObjectState state,
|
||||||
IDictionary<string, object> queryString,
|
IDictionary<string, object> queryString,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
var command = new AVCommand {
|
||||||
var command = new AVCommand(string.Format("classes/{0}/{1}?{2}",
|
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}",
|
||||||
Uri.EscapeDataString(state.ClassName),
|
Method = HttpMethod.Get
|
||||||
Uri.EscapeDataString(state.ObjectId),
|
};
|
||||||
AVClient.BuildQueryString(queryString)),
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||||
method: "GET",
|
|
||||||
sessionToken: sessionToken,
|
|
||||||
data: null);
|
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
|
||||||
{
|
|
||||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -56,22 +42,16 @@ namespace LeanCloud.Storage.Internal
|
||||||
public Task<IObjectState> SaveAsync(IObjectState state,
|
public Task<IObjectState> SaveAsync(IObjectState state,
|
||||||
IDictionary<string, IAVFieldOperation> operations,
|
IDictionary<string, IAVFieldOperation> operations,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
|
||||||
var objectJSON = AVObject.ToJSONObjectForSaving(operations);
|
var objectJSON = AVObject.ToJSONObjectForSaving(operations);
|
||||||
|
var command = new AVCommand {
|
||||||
var command = new AVCommand((state.ObjectId == null ?
|
Path = state.ObjectId == null ? $"classes/{Uri.EscapeDataString(state.ClassName)}" : $"classes/{Uri.EscapeDataString(state.ClassName)}/{state.ObjectId}",
|
||||||
string.Format("classes/{0}", Uri.EscapeDataString(state.ClassName)) :
|
Method = state.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
||||||
string.Format("classes/{0}/{1}", Uri.EscapeDataString(state.ClassName), state.ObjectId)),
|
Content = objectJSON
|
||||||
method: (state.ObjectId == null ? "POST" : "PUT"),
|
};
|
||||||
sessionToken: sessionToken,
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||||
data: objectJSON);
|
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
|
||||||
{
|
|
||||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
serverState = serverState.MutatedClone(mutableClone =>
|
serverState = serverState.MutatedClone(mutableClone => {
|
||||||
{
|
|
||||||
mutableClone.IsNew = t.Result.Item1 == System.Net.HttpStatusCode.Created;
|
mutableClone.IsNew = t.Result.Item1 == System.Net.HttpStatusCode.Created;
|
||||||
});
|
});
|
||||||
return serverState;
|
return serverState;
|
||||||
|
|
@ -81,24 +61,20 @@ namespace LeanCloud.Storage.Internal
|
||||||
public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
|
public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
|
||||||
IList<IDictionary<string, IAVFieldOperation>> operationsList,
|
IList<IDictionary<string, IAVFieldOperation>> operationsList,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
|
||||||
|
|
||||||
var requests = states
|
var requests = states
|
||||||
.Zip(operationsList, (item, ops) => new AVCommand(
|
.Zip(operationsList, (item, ops) => new AVCommand {
|
||||||
item.ObjectId == null
|
Path = item.ObjectId == null ? $"classes/{Uri.EscapeDataString(item.ClassName)}" : $"classes/{Uri.EscapeDataString(item.ClassName)}/{Uri.EscapeDataString(item.ObjectId)}",
|
||||||
? string.Format("classes/{0}", Uri.EscapeDataString(item.ClassName))
|
Method = item.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
||||||
: string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
|
Content = AVObject.ToJSONObjectForSaving(ops)
|
||||||
method: item.ObjectId == null ? "POST" : "PUT",
|
})
|
||||||
data: AVObject.ToJSONObjectForSaving(ops)))
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var batchTasks = ExecuteBatchRequests(requests, sessionToken, cancellationToken);
|
var batchTasks = ExecuteBatchRequests(requests, sessionToken, cancellationToken);
|
||||||
var stateTasks = new List<Task<IObjectState>>();
|
var stateTasks = new List<Task<IObjectState>>();
|
||||||
foreach (var task in batchTasks)
|
foreach (var task in batchTasks) {
|
||||||
{
|
stateTasks.Add(task.OnSuccess(t => {
|
||||||
stateTasks.Add(task.OnSuccess(t =>
|
|
||||||
{
|
|
||||||
return AVObjectCoder.Instance.Decode(t.Result, AVDecoder.Instance);
|
return AVObjectCoder.Instance.Decode(t.Result, AVDecoder.Instance);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
@ -108,27 +84,23 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
public Task DeleteAsync(IObjectState state,
|
public Task DeleteAsync(IObjectState state,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
var command = new AVCommand {
|
||||||
var command = new AVCommand(string.Format("classes/{0}/{1}",
|
Path = $"classes/{state.ClassName}/{state.ObjectId}",
|
||||||
state.ClassName, state.ObjectId),
|
Method = HttpMethod.Delete
|
||||||
method: "DELETE",
|
};
|
||||||
sessionToken: sessionToken,
|
|
||||||
data: null);
|
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
|
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
|
||||||
var requests = states
|
var requests = states
|
||||||
.Where(item => item.ObjectId != null)
|
.Where(item => item.ObjectId != null)
|
||||||
.Select(item => new AVCommand(
|
.Select(item => new AVCommand {
|
||||||
string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
|
Path = $"classes/{Uri.EscapeDataString(item.ClassName)}/{Uri.EscapeDataString(item.ObjectId)}",
|
||||||
method: "DELETE",
|
Method = HttpMethod.Delete
|
||||||
data: null))
|
})
|
||||||
.ToList();
|
.ToList();
|
||||||
return ExecuteBatchRequests(requests, sessionToken, cancellationToken).Cast<Task>().ToList();
|
return ExecuteBatchRequests(requests, sessionToken, cancellationToken).Cast<Task>().ToList();
|
||||||
}
|
}
|
||||||
|
|
@ -137,14 +109,12 @@ namespace LeanCloud.Storage.Internal
|
||||||
private const int MaximumBatchSize = 50;
|
private const int MaximumBatchSize = 50;
|
||||||
internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<AVCommand> requests,
|
internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<AVCommand> requests,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
|
||||||
var tasks = new List<Task<IDictionary<string, object>>>();
|
var tasks = new List<Task<IDictionary<string, object>>>();
|
||||||
int batchSize = requests.Count;
|
int batchSize = requests.Count;
|
||||||
|
|
||||||
IEnumerable<AVCommand> remaining = requests;
|
IEnumerable<AVCommand> remaining = requests;
|
||||||
while (batchSize > MaximumBatchSize)
|
while (batchSize > MaximumBatchSize) {
|
||||||
{
|
|
||||||
var process = remaining.Take(MaximumBatchSize).ToList();
|
var process = remaining.Take(MaximumBatchSize).ToList();
|
||||||
remaining = remaining.Skip(MaximumBatchSize);
|
remaining = remaining.Skip(MaximumBatchSize);
|
||||||
|
|
||||||
|
|
@ -159,48 +129,40 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<AVCommand> requests,
|
private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<AVCommand> requests,
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken) {
|
||||||
{
|
|
||||||
var tasks = new List<Task<IDictionary<string, object>>>();
|
var tasks = new List<Task<IDictionary<string, object>>>();
|
||||||
int batchSize = requests.Count;
|
int batchSize = requests.Count;
|
||||||
var tcss = new List<TaskCompletionSource<IDictionary<string, object>>>();
|
var tcss = new List<TaskCompletionSource<IDictionary<string, object>>>();
|
||||||
for (int i = 0; i < batchSize; ++i)
|
for (int i = 0; i < batchSize; ++i) {
|
||||||
{
|
|
||||||
var tcs = new TaskCompletionSource<IDictionary<string, object>>();
|
var tcs = new TaskCompletionSource<IDictionary<string, object>>();
|
||||||
tcss.Add(tcs);
|
tcss.Add(tcs);
|
||||||
tasks.Add(tcs.Task);
|
tasks.Add(tcs.Task);
|
||||||
}
|
}
|
||||||
|
|
||||||
var encodedRequests = requests.Select(r =>
|
var encodedRequests = requests.Select(r => {
|
||||||
{
|
|
||||||
var results = new Dictionary<string, object> {
|
var results = new Dictionary<string, object> {
|
||||||
{ "method", r.Method },
|
{ "method", r.Method },
|
||||||
{ "path", r.Uri.AbsolutePath },
|
{ "path", r.Path },
|
||||||
};
|
};
|
||||||
|
|
||||||
if (r.Body != null)
|
if (r.Content != null) {
|
||||||
{
|
results["body"] = r.Content;
|
||||||
results["body"] = r.Body;
|
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}).Cast<object>().ToList();
|
}).Cast<object>().ToList();
|
||||||
var command = new AVCommand("batch",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "batch",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: new Dictionary<string, object> { { "requests", encodedRequests } });
|
Content = new Dictionary<string, object> {
|
||||||
|
{ "requests", encodedRequests }
|
||||||
commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
}
|
||||||
{
|
};
|
||||||
if (t.IsFaulted || t.IsCanceled)
|
commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t => {
|
||||||
{
|
if (t.IsFaulted || t.IsCanceled) {
|
||||||
foreach (var tcs in tcss)
|
foreach (var tcs in tcss) {
|
||||||
{
|
if (t.IsFaulted) {
|
||||||
if (t.IsFaulted)
|
|
||||||
{
|
|
||||||
tcs.TrySetException(t.Exception);
|
tcs.TrySetException(t.Exception);
|
||||||
}
|
} else if (t.IsCanceled) {
|
||||||
else if (t.IsCanceled)
|
|
||||||
{
|
|
||||||
tcs.TrySetCanceled();
|
tcs.TrySetCanceled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -209,33 +171,25 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
var resultsArray = Conversion.As<IList<object>>(t.Result.Item2["results"]);
|
var resultsArray = Conversion.As<IList<object>>(t.Result.Item2["results"]);
|
||||||
int resultLength = resultsArray.Count;
|
int resultLength = resultsArray.Count;
|
||||||
if (resultLength != batchSize)
|
if (resultLength != batchSize) {
|
||||||
{
|
foreach (var tcs in tcss) {
|
||||||
foreach (var tcs in tcss)
|
|
||||||
{
|
|
||||||
tcs.TrySetException(new InvalidOperationException(
|
tcs.TrySetException(new InvalidOperationException(
|
||||||
"Batch command result count expected: " + batchSize + " but was: " + resultLength + "."));
|
"Batch command result count expected: " + batchSize + " but was: " + resultLength + "."));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < batchSize; ++i)
|
for (int i = 0; i < batchSize; ++i) {
|
||||||
{
|
|
||||||
var result = resultsArray[i] as Dictionary<string, object>;
|
var result = resultsArray[i] as Dictionary<string, object>;
|
||||||
var tcs = tcss[i];
|
var tcs = tcss[i];
|
||||||
|
|
||||||
if (result.ContainsKey("success"))
|
if (result.ContainsKey("success")) {
|
||||||
{
|
|
||||||
tcs.TrySetResult(result["success"] as IDictionary<string, object>);
|
tcs.TrySetResult(result["success"] as IDictionary<string, object>);
|
||||||
}
|
} else if (result.ContainsKey("error")) {
|
||||||
else if (result.ContainsKey("error"))
|
|
||||||
{
|
|
||||||
var error = result["error"] as IDictionary<string, object>;
|
var error = result["error"] as IDictionary<string, object>;
|
||||||
long errorCode = long.Parse(error["code"].ToString());
|
long errorCode = long.Parse(error["code"].ToString());
|
||||||
tcs.TrySetException(new AVException((AVException.ErrorCode)errorCode, error["error"] as string));
|
tcs.TrySetException(new AVException((AVException.ErrorCode)errorCode, error["error"] as string));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
tcs.TrySetException(new InvalidOperationException(
|
tcs.TrySetException(new InvalidOperationException(
|
||||||
"Invalid batch command response."));
|
"Invalid batch command response."));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Storage.Internal;
|
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
namespace LeanCloud.Storage.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -75,14 +74,10 @@ namespace LeanCloud.Storage.Internal
|
||||||
string sessionToken,
|
string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var command = new AVCommand {
|
||||||
var command = new AVCommand(string.Format("{0}?{1}",
|
Path = $"{relativeUri}?{AVClient.BuildQueryString(parameters)}",
|
||||||
relativeUri,
|
Method = HttpMethod.Get
|
||||||
AVClient.BuildQueryString(parameters)),
|
};
|
||||||
method: "GET",
|
|
||||||
sessionToken: sessionToken,
|
|
||||||
data: null);
|
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
return t.Result.Item2;
|
return t.Result.Item2;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Storage.Internal;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
public class AVSessionController : IAVSessionController {
|
public class AVSessionController : IAVSessionController {
|
||||||
|
|
@ -13,31 +13,28 @@ namespace LeanCloud.Storage.Internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IObjectState> GetSessionAsync(string sessionToken, CancellationToken cancellationToken) {
|
public Task<IObjectState> GetSessionAsync(string sessionToken, CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand("sessions/me",
|
var command = new AVCommand {
|
||||||
method: "GET",
|
Path = "sessions/me",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Get
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) {
|
public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand("logout",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "logout",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Post
|
||||||
data: new Dictionary<string, object>());
|
};
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IObjectState> UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) {
|
public Task<IObjectState> UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) {
|
||||||
var command = new AVCommand("upgradeToRevocableSession",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "upgradeToRevocableSession",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: new Dictionary<string, object>());
|
};
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Storage.Internal;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal
|
namespace LeanCloud.Storage.Internal
|
||||||
{
|
{
|
||||||
|
|
@ -20,11 +20,11 @@ namespace LeanCloud.Storage.Internal
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var objectJSON = AVObject.ToJSONObjectForSaving(operations);
|
var objectJSON = AVObject.ToJSONObjectForSaving(operations);
|
||||||
|
var command = new AVCommand {
|
||||||
var command = new AVCommand("classes/_User",
|
Path = "classes/_User",
|
||||||
method: "POST",
|
Method = HttpMethod.Post,
|
||||||
data: objectJSON);
|
Content = objectJSON
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
|
|
@ -49,11 +49,11 @@ namespace LeanCloud.Storage.Internal
|
||||||
if (email != null) {
|
if (email != null) {
|
||||||
data.Add("email", email);
|
data.Add("email", email);
|
||||||
}
|
}
|
||||||
|
var command = new AVCommand {
|
||||||
var command = new AVCommand("login",
|
Path = "login",
|
||||||
method: "POST",
|
Method = HttpMethod.Post,
|
||||||
data: data);
|
Content = data
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
|
|
@ -73,12 +73,13 @@ namespace LeanCloud.Storage.Internal
|
||||||
var authData = new Dictionary<string, object>();
|
var authData = new Dictionary<string, object>();
|
||||||
authData[authType] = data;
|
authData[authType] = data;
|
||||||
var path = failOnNotExist ? "users?failOnNotExist=true" : "users";
|
var path = failOnNotExist ? "users?failOnNotExist=true" : "users";
|
||||||
var command = new AVCommand(path,
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = path,
|
||||||
data: new Dictionary<string, object> {
|
Method = HttpMethod.Post,
|
||||||
|
Content = new Dictionary<string, object> {
|
||||||
{ "authData", authData}
|
{ "authData", authData}
|
||||||
});
|
}
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
|
|
@ -92,11 +93,10 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
public Task<IObjectState> GetUserAsync(string sessionToken, CancellationToken cancellationToken)
|
public Task<IObjectState> GetUserAsync(string sessionToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand("users/me",
|
var command = new AVCommand {
|
||||||
method: "GET",
|
Path = "users/me",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Get
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
|
|
@ -105,22 +105,24 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
public Task RequestPasswordResetAsync(string email, CancellationToken cancellationToken)
|
public Task RequestPasswordResetAsync(string email, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand("requestPasswordReset",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "requestPasswordReset",
|
||||||
data: new Dictionary<string, object> {
|
Method = HttpMethod.Post,
|
||||||
|
Content = new Dictionary<string, object> {
|
||||||
{ "email", email}
|
{ "email", email}
|
||||||
});
|
}
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IObjectState> LogInWithParametersAsync(string relativeUrl, IDictionary<string, object> data,
|
public Task<IObjectState> LogInWithParametersAsync(string relativeUrl, IDictionary<string, object> data,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand(string.Format("{0}", relativeUrl),
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = relativeUrl,
|
||||||
data: data);
|
Method = HttpMethod.Post,
|
||||||
|
Content = data
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
|
|
@ -134,23 +136,24 @@ namespace LeanCloud.Storage.Internal
|
||||||
|
|
||||||
public Task UpdatePasswordAsync(string userId, string sessionToken, string oldPassword, string newPassword, CancellationToken cancellationToken)
|
public Task UpdatePasswordAsync(string userId, string sessionToken, string oldPassword, string newPassword, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand(String.Format("users/{0}/updatePassword", userId),
|
var command = new AVCommand {
|
||||||
method: "PUT",
|
Path = $"users/{userId}/updatePassword",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Put,
|
||||||
data: new Dictionary<string, object> {
|
Content = new Dictionary<string, object> {
|
||||||
{"old_password", oldPassword},
|
{ "old_password", oldPassword },
|
||||||
{"new_password", newPassword},
|
{ "new_password", newPassword },
|
||||||
});
|
}
|
||||||
|
};
|
||||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IObjectState> RefreshSessionTokenAsync(string userId, string sessionToken,
|
public Task<IObjectState> RefreshSessionTokenAsync(string userId, string sessionToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand(String.Format("users/{0}/refreshSessionToken", userId),
|
var command = new AVCommand {
|
||||||
method: "PUT",
|
Path = $"users/{userId}/refreshSessionToken",
|
||||||
sessionToken: sessionToken,
|
Method = HttpMethod.Put
|
||||||
data: null);
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,12 @@ namespace LeanCloud
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string APIVersion {
|
||||||
|
get {
|
||||||
|
return "1.1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly string versionString;
|
private static readonly string versionString;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前 SDK 版本号
|
/// 当前 SDK 版本号
|
||||||
|
|
@ -431,16 +437,6 @@ namespace LeanCloud
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
return new Tuple<HttpStatusCode, IDictionary<string, object>>(code, strs);
|
return new Tuple<HttpStatusCode, IDictionary<string, object>>(code, strs);
|
||||||
}
|
}
|
||||||
internal static Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RequestAsync(string method, Uri relativeUri, string sessionToken, IDictionary<string, object> data, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
|
|
||||||
var command = new AVCommand(relativeUri.ToString(),
|
|
||||||
method: method,
|
|
||||||
sessionToken: sessionToken,
|
|
||||||
data: data);
|
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command)
|
internal static Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command)
|
||||||
{
|
{
|
||||||
|
|
@ -452,42 +448,5 @@ namespace LeanCloud
|
||||||
var codeValue = (int)responseStatus;
|
var codeValue = (int)responseStatus;
|
||||||
return (codeValue > 199) && (codeValue < 204);
|
return (codeValue > 199) && (codeValue < 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToLog(this HttpRequest request)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
var start = "===HTTP Request Start===";
|
|
||||||
sb.AppendLine(start);
|
|
||||||
var urlLog = "Url: " + request.Uri;
|
|
||||||
sb.AppendLine(urlLog);
|
|
||||||
|
|
||||||
var methodLog = "Method: " + request.Method;
|
|
||||||
sb.AppendLine(methodLog);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var headers = request.Headers.ToDictionary(x => x.Key, x => x.Value as object);
|
|
||||||
var headersLog = "Headers: " + Json.Encode(headers);
|
|
||||||
sb.AppendLine(headersLog);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var bodyLog = "Body:" + Json.Encode(request.Data);
|
|
||||||
sb.AppendLine(bodyLog);
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var end = "===HTTP Request End===";
|
|
||||||
sb.AppendLine(end);
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Storage.Internal;
|
using LeanCloud.Storage.Internal;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud {
|
namespace LeanCloud {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -77,37 +78,6 @@ namespace LeanCloud {
|
||||||
}).Unwrap();
|
}).Unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取 LeanCloud 服务器的时间
|
|
||||||
/// <remarks>
|
|
||||||
/// 如果获取失败,将返回 DateTime.MinValue
|
|
||||||
/// </remarks>
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>服务器的时间</returns>
|
|
||||||
public static Task<DateTime> GetServerDateTimeAsync()
|
|
||||||
{
|
|
||||||
var command = new AVCommand(relativeUri: "date",
|
|
||||||
method: "GET",
|
|
||||||
sessionToken: null,
|
|
||||||
data: null);
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
|
||||||
{
|
|
||||||
DateTime rtn = DateTime.MinValue;
|
|
||||||
if (AVClient.IsSuccessStatusCode(t.Result.Item1))
|
|
||||||
{
|
|
||||||
var date = AVDecoder.Instance.Decode(t.Result.Item2);
|
|
||||||
if (date != null)
|
|
||||||
{
|
|
||||||
if (date is DateTime)
|
|
||||||
{
|
|
||||||
rtn = (DateTime)date;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rtn;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求短信认证。
|
/// 请求短信认证。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -154,10 +124,11 @@ namespace LeanCloud {
|
||||||
{
|
{
|
||||||
strs.Add("TTL", ttl);
|
strs.Add("TTL", ttl);
|
||||||
}
|
}
|
||||||
var command = new AVCommand("requestSmsCode",
|
var command = new EngineCommand {
|
||||||
method: "POST",
|
Path = "requestSmsCode",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Post,
|
||||||
data: strs);
|
Content = strs
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -227,10 +198,11 @@ namespace LeanCloud {
|
||||||
{
|
{
|
||||||
strs.Add(key, env[key]);
|
strs.Add(key, env[key]);
|
||||||
}
|
}
|
||||||
var command = new AVCommand("requestSmsCode",
|
var command = new EngineCommand {
|
||||||
method: "POST",
|
Path = "requestSmsCode",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Post,
|
||||||
data: strs);
|
Content = strs
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -248,17 +220,18 @@ namespace LeanCloud {
|
||||||
{
|
{
|
||||||
throw new AVException(AVException.ErrorCode.MobilePhoneInvalid, "Moblie Phone number is invalid.", null);
|
throw new AVException(AVException.ErrorCode.MobilePhoneInvalid, "Moblie Phone number is invalid.", null);
|
||||||
}
|
}
|
||||||
Dictionary<string, object> strs = new Dictionary<string, object>()
|
Dictionary<string, object> body = new Dictionary<string, object>()
|
||||||
{
|
{
|
||||||
{ "mobilePhoneNumber", mobilePhoneNumber },
|
{ "mobilePhoneNumber", mobilePhoneNumber },
|
||||||
{ "smsType", "voice" },
|
{ "smsType", "voice" },
|
||||||
{ "IDD","+86" }
|
{ "IDD", "+86" }
|
||||||
};
|
};
|
||||||
|
|
||||||
var command = new AVCommand("requestSmsCode",
|
var command = new EngineCommand {
|
||||||
method: "POST",
|
Path = "requestSmsCode",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Post,
|
||||||
data: strs);
|
Content = body
|
||||||
|
};
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
|
|
@ -286,11 +259,9 @@ namespace LeanCloud {
|
||||||
/// <param name="cancellationToken">Cancellation token.</param>
|
/// <param name="cancellationToken">Cancellation token.</param>
|
||||||
public static Task<bool> VerifySmsCodeAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken)
|
public static Task<bool> VerifySmsCodeAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand("verifySmsCode/" + code.Trim() + "?mobilePhoneNumber=" + mobilePhoneNumber.Trim(),
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = $"verifySmsCode/{code.Trim()}?mobilePhoneNumber={mobilePhoneNumber.Trim()}",
|
||||||
sessionToken: null,
|
};
|
||||||
data: null);
|
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -334,7 +305,10 @@ namespace LeanCloud {
|
||||||
public static Task<Captcha> RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default(CancellationToken))
|
public static Task<Captcha> RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
var path = String.Format("requestCaptcha?width={0}&height={1}", width, height);
|
var path = String.Format("requestCaptcha?width={0}&height={1}", width, height);
|
||||||
var command = new AVCommand(path, method: "GET", sessionToken: null, data: null);
|
var command = new AVCommand {
|
||||||
|
Path = $"requestCaptcha?width={width}&height={height}",
|
||||||
|
Method = HttpMethod.Get
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
||||||
|
|
@ -355,12 +329,15 @@ namespace LeanCloud {
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Task<string> VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default(CancellationToken))
|
public static Task<string> VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
var data = new Dictionary<string, object>
|
var data = new Dictionary<string, object> {
|
||||||
{
|
|
||||||
{ "captcha_token", token },
|
{ "captcha_token", token },
|
||||||
{ "captcha_code", code },
|
{ "captcha_code", code },
|
||||||
};
|
};
|
||||||
var command = new AVCommand("verifyCaptcha", method: "POST", sessionToken: null, data: data);
|
var command = new AVCommand {
|
||||||
|
Path = "verifyCaptcha",
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
Content = data
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
if (!t.Result.Item2.ContainsKey("validate_token"))
|
if (!t.Result.Item2.ContainsKey("validate_token"))
|
||||||
|
|
@ -376,11 +353,10 @@ namespace LeanCloud {
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Task<IDictionary<string, object>> GetCustomParametersAsync(CancellationToken cancellationToken = default(CancellationToken))
|
public static Task<IDictionary<string, object>> GetCustomParametersAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
var command = new AVCommand(string.Format("statistics/apps/{0}/sendPolicy", AVClient.CurrentConfiguration.ApplicationId),
|
var command = new AVCommand {
|
||||||
method: "GET",
|
Path = $"statistics/apps/{AVClient.CurrentConfiguration.ApplicationId}/sendPolicy",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Get
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var settings = t.Result.Item2;
|
var settings = t.Result.Item2;
|
||||||
|
|
@ -407,14 +383,13 @@ namespace LeanCloud {
|
||||||
|
|
||||||
public static Task<RealtimeSignature> RequestRealtimeSignatureAsync(AVUser user, CancellationToken cancellationToken = default(CancellationToken))
|
public static Task<RealtimeSignature> RequestRealtimeSignatureAsync(AVUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
var command = new AVCommand(string.Format("rtm/sign"),
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "rtm/sign",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Post,
|
||||||
data: new Dictionary<string, object>
|
Content = new Dictionary<string, string> {
|
||||||
{
|
{ "session_token", user.SessionToken }
|
||||||
{ "session_token", user.SessionToken },
|
}
|
||||||
}
|
};
|
||||||
);
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
var body = t.Result.Item2;
|
var body = t.Result.Item2;
|
||||||
|
|
@ -517,12 +492,11 @@ namespace LeanCloud {
|
||||||
{
|
{
|
||||||
var user = t.Result;
|
var user = t.Result;
|
||||||
var encodedParameters = Encode(parameters);
|
var encodedParameters = Encode(parameters);
|
||||||
var command = new AVCommand(
|
var command = new EngineCommand {
|
||||||
string.Format("call/{0}", Uri.EscapeUriString(this.FunctionName)),
|
Path = $"call/{Uri.EscapeUriString(FunctionName)}",
|
||||||
method: "POST",
|
Method = HttpMethod.Post,
|
||||||
sessionToken: user != null ? user.SessionToken : null,
|
Content = encodedParameters
|
||||||
data: encodedParameters);
|
};
|
||||||
|
|
||||||
return AVClient.RunCommandAsync(command);
|
return AVClient.RunCommandAsync(command);
|
||||||
|
|
||||||
}).Unwrap().OnSuccess(s =>
|
}).Unwrap().OnSuccess(s =>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
@ -355,14 +355,18 @@ namespace LeanCloud
|
||||||
};
|
};
|
||||||
AVCommand cmd = null;
|
AVCommand cmd = null;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(this.ObjectId))
|
if (!string.IsNullOrEmpty(this.ObjectId)) {
|
||||||
{
|
cmd = new AVCommand {
|
||||||
cmd = new AVCommand("files/" + this.ObjectId,
|
Path = $"files/{ObjectId}",
|
||||||
method: "PUT", sessionToken: AVUser.CurrentSessionToken, data: strs);
|
Method = HttpMethod.Put,
|
||||||
}
|
Content = strs
|
||||||
else
|
};
|
||||||
{
|
} else {
|
||||||
cmd = new AVCommand("files", method: "POST", sessionToken: AVUser.CurrentSessionToken, data: strs);
|
cmd = new AVCommand {
|
||||||
|
Path = "files",
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
Content = strs
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(cmd).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(cmd).ContinueWith(t =>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using LeanCloud.Storage.Internal;
|
using LeanCloud.Storage.Internal;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace LeanCloud
|
namespace LeanCloud
|
||||||
{
|
{
|
||||||
|
|
@ -209,7 +208,7 @@ namespace LeanCloud
|
||||||
}).Unwrap().OnSuccess(t =>
|
}).Unwrap().OnSuccess(t =>
|
||||||
{
|
{
|
||||||
IObjectState state = t.Result;
|
IObjectState state = t.Result;
|
||||||
return state == null ? default(T) : AVObject.FromState<T>(state, ClassName);
|
return state == null ? default : AVObject.FromState<T>(state, ClassName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -310,11 +309,10 @@ namespace LeanCloud
|
||||||
|
|
||||||
internal static Task<IEnumerable<T>> rebuildObjectFromCloudQueryResult(string queryString)
|
internal static Task<IEnumerable<T>> rebuildObjectFromCloudQueryResult(string queryString)
|
||||||
{
|
{
|
||||||
var command = new AVCommand(queryString,
|
var command = new AVCommand {
|
||||||
method: "GET",
|
Path = queryString,
|
||||||
sessionToken: AVUser.CurrentSessionToken,
|
Method = HttpMethod.Get
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: CancellationToken.None).OnSuccess(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: CancellationToken.None).OnSuccess(t =>
|
||||||
{
|
{
|
||||||
var items = t.Result.Item2["results"] as IList<object>;
|
var items = t.Result.Item2["results"] as IList<object>;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
using LeanCloud.Storage.Internal;
|
using LeanCloud.Storage.Internal;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Net.Http;
|
||||||
using System.Net;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
|
@ -69,9 +67,10 @@ namespace LeanCloud
|
||||||
return Task.FromResult(false);
|
return Task.FromResult(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var command = new AVCommand(String.Format("users/me?session_token={0}", CurrentSessionToken),
|
var command = new AVCommand {
|
||||||
method: "GET",
|
Path = $"users/me?session_token={CurrentSessionToken}",
|
||||||
data: null);
|
Method = HttpMethod.Get
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -297,10 +296,11 @@ namespace LeanCloud
|
||||||
{
|
{
|
||||||
data = this.EncodeForSaving(data);
|
data = this.EncodeForSaving(data);
|
||||||
}
|
}
|
||||||
var command = new AVCommand(string.Format("users/{0}/friendship/{1}", this.ObjectId, userObjectId),
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = $"users/{ObjectId}/friendship/{userObjectId}",
|
||||||
sessionToken: CurrentSessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: data);
|
Content = data
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -314,10 +314,10 @@ namespace LeanCloud
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task<bool> UnfollowAsync(string userObjectId)
|
public Task<bool> UnfollowAsync(string userObjectId)
|
||||||
{
|
{
|
||||||
var command = new AVCommand(string.Format("users/{0}/friendship/{1}", this.ObjectId, userObjectId),
|
var command = new AVCommand {
|
||||||
method: "DELETE",
|
Path = $"users/{ObjectId}/friendship/{userObjectId}",
|
||||||
sessionToken: CurrentSessionToken,
|
Method = HttpMethod.Delete
|
||||||
data: null);
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -1045,10 +1045,11 @@ namespace LeanCloud
|
||||||
{
|
{
|
||||||
strs.Add("validate_token", validateToken);
|
strs.Add("validate_token", validateToken);
|
||||||
}
|
}
|
||||||
var command = new AVCommand("requestLoginSmsCode",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "requestLoginSmsCode",
|
||||||
sessionToken: CurrentSessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: strs);
|
Content = strs
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -1183,10 +1184,11 @@ namespace LeanCloud
|
||||||
{
|
{
|
||||||
strs.Add("validate_token", validateToken);
|
strs.Add("validate_token", validateToken);
|
||||||
}
|
}
|
||||||
var command = new AVCommand("requestPasswordResetBySmsCode",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "requestPasswordResetBySmsCode",
|
||||||
sessionToken: currentSessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: strs);
|
Content = strs
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -1218,10 +1220,11 @@ namespace LeanCloud
|
||||||
{
|
{
|
||||||
{ "password", newPassword }
|
{ "password", newPassword }
|
||||||
};
|
};
|
||||||
var command = new AVCommand("resetPasswordBySmsCode/" + smsCode,
|
var command = new AVCommand {
|
||||||
method: "PUT",
|
Path = $"resetPasswordBySmsCode/{smsCode}",
|
||||||
sessionToken: currentSessionToken,
|
Method = HttpMethod.Put,
|
||||||
data: strs);
|
Content = strs
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -1278,10 +1281,11 @@ namespace LeanCloud
|
||||||
{
|
{
|
||||||
strs.Add("validate_token", validateToken);
|
strs.Add("validate_token", validateToken);
|
||||||
}
|
}
|
||||||
var command = new AVCommand("requestMobilePhoneVerify",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "requestMobilePhoneVerify",
|
||||||
sessionToken: currentSessionToken,
|
Method = HttpMethod.Post,
|
||||||
data: strs);
|
Content = strs
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -1308,10 +1312,10 @@ namespace LeanCloud
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Task<bool> VerifyMobilePhoneAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken)
|
public static Task<bool> VerifyMobilePhoneAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var command = new AVCommand("verifyMobilePhone/" + code.Trim() + "?mobilePhoneNumber=" + mobilePhoneNumber.Trim(),
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = $"verifyMobilePhone/{code.Trim()}?mobilePhoneNumber={mobilePhoneNumber.Trim()}",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Post
|
||||||
data: null);
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -1325,11 +1329,10 @@ namespace LeanCloud
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Task<bool> VerifyMobilePhoneAsync(string code)
|
public static Task<bool> VerifyMobilePhoneAsync(string code)
|
||||||
{
|
{
|
||||||
var command = new AVCommand("verifyMobilePhone/" + code.Trim(),
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = $"verifyMobilePhone/{code.Trim()}",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Post
|
||||||
data: null);
|
};
|
||||||
|
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
@ -1363,10 +1366,11 @@ namespace LeanCloud
|
||||||
{
|
{
|
||||||
{ "email", email }
|
{ "email", email }
|
||||||
};
|
};
|
||||||
var command = new AVCommand("requestEmailVerify",
|
var command = new AVCommand {
|
||||||
method: "POST",
|
Path = "requestEmailVerify",
|
||||||
sessionToken: null,
|
Method = HttpMethod.Post,
|
||||||
data: strs);
|
Content = strs
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||||
{
|
{
|
||||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using LeanCloud.Storage.Internal;
|
using LeanCloud.Storage.Internal;
|
||||||
using System.IO;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace LeanCloud {
|
namespace LeanCloud {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -153,7 +152,11 @@ namespace LeanCloud {
|
||||||
{ "versionChangeInterval", versionChangeInterval.ToString().ToLower() },
|
{ "versionChangeInterval", versionChangeInterval.ToString().ToLower() },
|
||||||
{ "updateStrategy", updateStrategy.ToString().ToLower() },
|
{ "updateStrategy", updateStrategy.ToString().ToLower() },
|
||||||
};
|
};
|
||||||
var command = new AVCommand("leaderboard/leaderboards", "POST", data: data);
|
var command = new AVCommand {
|
||||||
|
Path = "leaderboard/leaderboards",
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
Content = data
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
try {
|
try {
|
||||||
var leaderboard = Parse(t.Result.Item2);
|
var leaderboard = Parse(t.Result.Item2);
|
||||||
|
|
@ -211,7 +214,11 @@ namespace LeanCloud {
|
||||||
if (overwrite) {
|
if (overwrite) {
|
||||||
path = string.Format("{0}?overwrite=1", path);
|
path = string.Format("{0}?overwrite=1", path);
|
||||||
}
|
}
|
||||||
var command = new AVCommand(path, "POST", user.SessionToken, data: data);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
Content = data
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
try {
|
try {
|
||||||
List<AVStatistic> statisticList = new List<AVStatistic>();
|
List<AVStatistic> statisticList = new List<AVStatistic>();
|
||||||
|
|
@ -242,7 +249,10 @@ namespace LeanCloud {
|
||||||
path = string.Format("{0}?statistics={1}", path, names);
|
path = string.Format("{0}?statistics={1}", path, names);
|
||||||
}
|
}
|
||||||
var sessionToken = AVUser.CurrentUser?.SessionToken;
|
var sessionToken = AVUser.CurrentUser?.SessionToken;
|
||||||
var command = new AVCommand(path, "GET", sessionToken, data: null);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Post
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
try {
|
try {
|
||||||
List<AVStatistic> statisticList = new List<AVStatistic>();
|
List<AVStatistic> statisticList = new List<AVStatistic>();
|
||||||
|
|
@ -272,7 +282,10 @@ namespace LeanCloud {
|
||||||
var path = string.Format("leaderboard/users/{0}/statistics", user.ObjectId);
|
var path = string.Format("leaderboard/users/{0}/statistics", user.ObjectId);
|
||||||
var names = string.Join(",", statisticNames.ToArray());
|
var names = string.Join(",", statisticNames.ToArray());
|
||||||
path = string.Format("{0}?statistics={1}", path, names);
|
path = string.Format("{0}?statistics={1}", path, names);
|
||||||
var command = new AVCommand(path, "DELETE", sessionToken: user.SessionToken, data: null);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Delete,
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command);
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,7 +298,10 @@ namespace LeanCloud {
|
||||||
public Task<List<AVLeaderboardArchive>> GetArchives(int skip = 0, int limit = 10) {
|
public Task<List<AVLeaderboardArchive>> GetArchives(int skip = 0, int limit = 10) {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}/archives", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}/archives", StatisticName);
|
||||||
path = string.Format("{0}?skip={1}&limit={2}", path, skip, limit);
|
path = string.Format("{0}?skip={1}&limit={2}", path, skip, limit);
|
||||||
var command = new AVCommand(path, "GET", data: null);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Get
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
|
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
|
||||||
List<object> list = t.Result.Item2["results"] as List<object>;
|
List<object> list = t.Result.Item2["results"] as List<object>;
|
||||||
|
|
@ -342,7 +358,10 @@ namespace LeanCloud {
|
||||||
var statistics = string.Join(",", includeStatistics.ToArray());
|
var statistics = string.Join(",", includeStatistics.ToArray());
|
||||||
path = string.Format("{0}&includeStatistics={1}", path, statistics);
|
path = string.Format("{0}&includeStatistics={1}", path, statistics);
|
||||||
}
|
}
|
||||||
var command = new AVCommand(path, "GET", data: null);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Get
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
try {
|
try {
|
||||||
List<AVRanking> rankingList = new List<AVRanking>();
|
List<AVRanking> rankingList = new List<AVRanking>();
|
||||||
|
|
@ -389,7 +408,11 @@ namespace LeanCloud {
|
||||||
|
|
||||||
Task<IDictionary<string,object>> Update(Dictionary<string, object> data) {
|
Task<IDictionary<string,object>> Update(Dictionary<string, object> data) {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
||||||
var command = new AVCommand(path, "PUT", data: data);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Put,
|
||||||
|
Content = data
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
return t.Result.Item2;
|
return t.Result.Item2;
|
||||||
});
|
});
|
||||||
|
|
@ -401,7 +424,10 @@ namespace LeanCloud {
|
||||||
/// <returns>排行榜对象</returns>
|
/// <returns>排行榜对象</returns>
|
||||||
public Task<AVLeaderboard> Fetch() {
|
public Task<AVLeaderboard> Fetch() {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
||||||
var command = new AVCommand(path, "GET", data: null);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Get
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
try {
|
try {
|
||||||
// 反序列化 Leaderboard 对象
|
// 反序列化 Leaderboard 对象
|
||||||
|
|
@ -419,7 +445,10 @@ namespace LeanCloud {
|
||||||
/// <returns>排行榜对象</returns>
|
/// <returns>排行榜对象</returns>
|
||||||
public Task<AVLeaderboard> Reset() {
|
public Task<AVLeaderboard> Reset() {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}/incrementVersion", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}/incrementVersion", StatisticName);
|
||||||
var command = new AVCommand(path, "PUT", data: null);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Put
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
|
||||||
try {
|
try {
|
||||||
Init(t.Result.Item2);
|
Init(t.Result.Item2);
|
||||||
|
|
@ -435,7 +464,10 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Task Destroy() {
|
public Task Destroy() {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
||||||
var command = new AVCommand(path, "DELETE", data: null);
|
var command = new AVCommand {
|
||||||
|
Path = path,
|
||||||
|
Method = HttpMethod.Delete
|
||||||
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command);
|
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue