chore: 重构了 AVCommand 及 http 模块
parent
c6bbf3219f
commit
ca3b19311c
|
@ -10,6 +10,7 @@ namespace LeanCloudTests {
|
|||
AVClient.Initialize(new AVClient.Configuration {
|
||||
ApplicationId = "BMYV4RKSTwo8WSqt8q9ezcWF-gzGzoHsz",
|
||||
ApplicationKey = "pbf6Nk5seyjilexdpyrPwjSp",
|
||||
ApiServer = "https://avoscloud.com"
|
||||
});
|
||||
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.Tasks;
|
||||
using LeanCloud.Utilities;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud.Storage.Internal
|
||||
{
|
||||
|
@ -21,11 +21,11 @@ namespace LeanCloud.Storage.Internal
|
|||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand(string.Format("functions/{0}", Uri.EscapeUriString(name)),
|
||||
method: "POST",
|
||||
sessionToken: sessionToken,
|
||||
data: NoObjectsEncoder.Instance.Encode(parameters) as IDictionary<string, object>);
|
||||
|
||||
var command = new EngineCommand {
|
||||
Path = $"functions/{Uri.EscapeUriString(name)}",
|
||||
Method = HttpMethod.Post,
|
||||
Content = parameters
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
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)
|
||||
{
|
||||
var command = new AVCommand(string.Format("call/{0}", Uri.EscapeUriString(name)),
|
||||
method: "POST",
|
||||
sessionToken: sessionToken,
|
||||
data: PointerOrLocalIdEncoder.Instance.Encode(parameters) as IDictionary<string, object>);
|
||||
|
||||
var command = new EngineCommand {
|
||||
Path = $"call/{Uri.EscapeUriString(name)}",
|
||||
Method = HttpMethod.Post,
|
||||
Content = parameters
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
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
|
||||
/// headers.
|
||||
/// </summary>
|
||||
public class AVCommand : HttpRequest
|
||||
{
|
||||
public object Body {
|
||||
public class AVCommand {
|
||||
// 不同服务对应的服务器地址不同
|
||||
public virtual string Server => AVClient.CurrentConfiguration.ApiServer;
|
||||
|
||||
public string Path {
|
||||
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 {
|
||||
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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace LeanCloud.Storage.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Command Runner.
|
||||
/// </summary>
|
||||
public class AVCommandRunner : IAVCommandRunner
|
||||
{
|
||||
private readonly IHttpClient httpClient;
|
||||
public class AVCommandRunner : IAVCommandRunner {
|
||||
public const string APPLICATION_JSON = "application/json";
|
||||
|
||||
private readonly System.Net.Http.HttpClient httpClient;
|
||||
private readonly IInstallationIdController installationIdController;
|
||||
|
||||
/// <summary>
|
||||
|
@ -23,7 +26,7 @@ namespace LeanCloud.Storage.Internal
|
|||
/// <param name="installationIdController"></param>
|
||||
public AVCommandRunner(IHttpClient httpClient, IInstallationIdController installationIdController)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.httpClient = new System.Net.Http.HttpClient();
|
||||
this.installationIdController = installationIdController;
|
||||
}
|
||||
|
||||
|
@ -35,133 +38,113 @@ namespace LeanCloud.Storage.Internal
|
|||
/// <param name="downloadProgress"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <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<AVDownloadProgressEventArgs> downloadProgress = null,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return PrepareCommand(command).ContinueWith(commandTask =>
|
||||
{
|
||||
var requestLog = commandTask.Result.ToLog();
|
||||
AVClient.PrintLog("http=>" + requestLog);
|
||||
CancellationToken cancellationToken = default(CancellationToken)) {
|
||||
|
||||
var request = new HttpRequestMessage {
|
||||
RequestUri = command.Uri,
|
||||
Method = command.Method,
|
||||
Content = new StringContent(Json.Encode(command.Content))
|
||||
};
|
||||
|
||||
return httpClient.ExecuteAsync(commandTask.Result, uploadProgress, downloadProgress, cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var headers = await GetHeadersAsync();
|
||||
foreach (var header in headers) {
|
||||
if (!string.IsNullOrEmpty(header.Value)) {
|
||||
request.Headers.Add(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue(APPLICATION_JSON);
|
||||
|
||||
var response = t.Result;
|
||||
var contentString = response.Item2;
|
||||
int responseCode = (int)response.Item1;
|
||||
PrintRequest(command, headers);
|
||||
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||
request.Dispose();
|
||||
|
||||
var responseLog = responseCode + ";" + contentString;
|
||||
AVClient.PrintLog("http<=" + responseLog);
|
||||
var resultString = await response.Content.ReadAsStringAsync();
|
||||
response.Dispose();
|
||||
PrintResponse(response, resultString);
|
||||
|
||||
if (responseCode >= 500)
|
||||
{
|
||||
// Server error, return InternalServerError.
|
||||
throw new AVException(AVException.ErrorCode.InternalServerError, response.Item2);
|
||||
var ret = new Tuple<HttpStatusCode, string>(response.StatusCode, resultString);
|
||||
|
||||
var responseCode = ret.Item1;
|
||||
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)
|
||||
{
|
||||
IDictionary<string, object> contentJson = null;
|
||||
try
|
||||
{
|
||||
if (contentString.StartsWith("["))
|
||||
{
|
||||
var arrayJson = Json.Parse(contentString);
|
||||
contentJson = new Dictionary<string, object> { { "results", arrayJson } };
|
||||
}
|
||||
else
|
||||
{
|
||||
contentJson = Json.Parse(contentString) as IDictionary<string, object>;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
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();
|
||||
} catch (Exception e) {
|
||||
throw new AVException(AVException.ErrorCode.OtherCause,
|
||||
"Invalid response from server", e);
|
||||
}
|
||||
if (responseCode < HttpStatusCode.OK || responseCode > HttpStatusCode.PartialContent) {
|
||||
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>>(responseCode, contentJson);
|
||||
}
|
||||
|
||||
return new Tuple<HttpStatusCode, IDictionary<string, object>>(responseCode, null);
|
||||
}
|
||||
|
||||
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;
|
||||
if (!string.IsNullOrEmpty(configuration.MasterKey) && AVClient.UseMasterKey)
|
||||
{
|
||||
string sign = MD5.GetMd5String(timestamp + configuration.MasterKey);
|
||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Sign", string.Format("{0},{1},master", sign, timestamp)));
|
||||
}
|
||||
else
|
||||
{
|
||||
string sign = MD5.GetMd5String(timestamp + configuration.ApplicationKey);
|
||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Sign", string.Format("{0},{1}", sign, timestamp)));
|
||||
if (!string.IsNullOrEmpty(conf.MasterKey) && AVClient.UseMasterKey) {
|
||||
string sign = MD5.GetMd5String(timestamp + conf.MasterKey);
|
||||
headers.Add("X-LC-Sign", $"{sign},{timestamp},master");
|
||||
} else {
|
||||
string sign = MD5.GetMd5String(timestamp + conf.ApplicationKey);
|
||||
headers.Add("X-LC-Sign", $"{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))
|
||||
{
|
||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-App-Build-Version", configuration.VersionInfo.BuildVersion));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(configuration.VersionInfo.DisplayVersion))
|
||||
{
|
||||
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-App-Display-Version", configuration.VersionInfo.DisplayVersion));
|
||||
}
|
||||
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;
|
||||
static void PrintResponse(HttpResponseMessage response, string content) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("=== HTTP Response Start ===");
|
||||
sb.AppendLine($"URL: {response.RequestMessage.RequestUri}");
|
||||
sb.AppendLine($"Content: {content}");
|
||||
sb.AppendLine("=== HTTP Response End ===");
|
||||
AVClient.PrintLog(sb.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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="cancellationToken">The cancellation token for the request.</param>
|
||||
/// <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<AVDownloadProgressEventArgs> downloadProgress = null,
|
||||
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.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud.Storage.Internal {
|
||||
/// <summary>
|
||||
|
@ -22,10 +22,10 @@ namespace LeanCloud.Storage.Internal {
|
|||
public IAVCurrentConfigController CurrentConfigController { get; internal set; }
|
||||
|
||||
public Task<AVConfig> FetchConfigAsync(String sessionToken, CancellationToken cancellationToken) {
|
||||
var command = new AVCommand("config",
|
||||
method: "GET",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
var command = new AVCommand {
|
||||
Path = "config",
|
||||
Method = HttpMethod.Post,
|
||||
};
|
||||
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(task => {
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace LeanCloud.Storage.Internal
|
|||
/// </summary>
|
||||
public class AVFileController : IAVFileController
|
||||
{
|
||||
private readonly IAVCommandRunner commandRunner;
|
||||
protected readonly IAVCommandRunner commandRunner;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:LeanCloud.Storage.Internal.AVFileController"/> class.
|
||||
/// </summary>
|
||||
|
@ -66,14 +66,13 @@ namespace LeanCloud.Storage.Internal
|
|||
}
|
||||
public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand("files/" + state.ObjectId,
|
||||
method: "DELETE",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = $"files/{state.ObjectId}",
|
||||
Method = HttpMethod.Delete
|
||||
};
|
||||
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;
|
||||
string currentSessionToken = AVUser.CurrentSessionToken;
|
||||
|
@ -85,17 +84,19 @@ namespace LeanCloud.Storage.Internal
|
|||
parameters.Add("mime_type", AVFile.GetMIMEType(str));
|
||||
parameters.Add("metaData", fileState.MetaData);
|
||||
|
||||
rtn = AVClient.RequestAsync("POST", new Uri("fileTokens", UriKind.Relative), currentSessionToken, parameters, cancellationToken);
|
||||
|
||||
return rtn;
|
||||
var command = new AVCommand {
|
||||
Path = "fileTokens",
|
||||
Method = HttpMethod.Post,
|
||||
Content = parameters
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command);
|
||||
}
|
||||
public Task<FileState> GetAsync(string objectId, string sessionToken, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand("files/" + objectId,
|
||||
method: "GET",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = $"files/{objectId}",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(_ =>
|
||||
{
|
||||
var result = _.Result;
|
||||
|
|
|
@ -161,9 +161,12 @@ namespace LeanCloud.Storage.Internal
|
|||
|
||||
parameters.Add("metaData", state.MetaData);
|
||||
|
||||
rtn = AVClient.RequestAsync("POST", new Uri("qiniu", UriKind.Relative), currentSessionToken, parameters, cancellationToken);
|
||||
|
||||
return rtn;
|
||||
var command = new AVCommand {
|
||||
Path = "qiniu",
|
||||
Method = HttpMethod.Post,
|
||||
Content = parameters
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command);
|
||||
}
|
||||
IList<KeyValuePair<string, string>> GetQiniuRequestHeaders(FileState state)
|
||||
{
|
||||
|
|
|
@ -4,32 +4,24 @@ using System.Collections.Generic;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LeanCloud.Utilities;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud.Storage.Internal
|
||||
{
|
||||
public class AVObjectController : IAVObjectController
|
||||
{
|
||||
namespace LeanCloud.Storage.Internal {
|
||||
public class AVObjectController : IAVObjectController {
|
||||
private readonly IAVCommandRunner commandRunner;
|
||||
|
||||
public AVObjectController(IAVCommandRunner commandRunner)
|
||||
{
|
||||
public AVObjectController(IAVCommandRunner commandRunner) {
|
||||
this.commandRunner = commandRunner;
|
||||
}
|
||||
|
||||
public Task<IObjectState> FetchAsync(IObjectState state,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand(string.Format("classes/{0}/{1}",
|
||||
Uri.EscapeDataString(state.ClassName),
|
||||
Uri.EscapeDataString(state.ObjectId)),
|
||||
method: "GET",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
CancellationToken cancellationToken) {
|
||||
var command = new AVCommand {
|
||||
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||
});
|
||||
}
|
||||
|
@ -37,18 +29,12 @@ namespace LeanCloud.Storage.Internal
|
|||
public Task<IObjectState> FetchAsync(IObjectState state,
|
||||
IDictionary<string, object> queryString,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand(string.Format("classes/{0}/{1}?{2}",
|
||||
Uri.EscapeDataString(state.ClassName),
|
||||
Uri.EscapeDataString(state.ObjectId),
|
||||
AVClient.BuildQueryString(queryString)),
|
||||
method: "GET",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
CancellationToken cancellationToken) {
|
||||
var command = new AVCommand {
|
||||
Path = $"classes/{Uri.EscapeDataString(state.ClassName)}/{Uri.EscapeDataString(state.ObjectId)}?{AVClient.BuildQueryString(queryString)}",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||
});
|
||||
}
|
||||
|
@ -56,22 +42,16 @@ namespace LeanCloud.Storage.Internal
|
|||
public Task<IObjectState> SaveAsync(IObjectState state,
|
||||
IDictionary<string, IAVFieldOperation> operations,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
CancellationToken cancellationToken) {
|
||||
var objectJSON = AVObject.ToJSONObjectForSaving(operations);
|
||||
|
||||
var command = new AVCommand((state.ObjectId == null ?
|
||||
string.Format("classes/{0}", Uri.EscapeDataString(state.ClassName)) :
|
||||
string.Format("classes/{0}/{1}", Uri.EscapeDataString(state.ClassName), state.ObjectId)),
|
||||
method: (state.ObjectId == null ? "POST" : "PUT"),
|
||||
sessionToken: sessionToken,
|
||||
data: objectJSON);
|
||||
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
var command = new AVCommand {
|
||||
Path = state.ObjectId == null ? $"classes/{Uri.EscapeDataString(state.ClassName)}" : $"classes/{Uri.EscapeDataString(state.ClassName)}/{state.ObjectId}",
|
||||
Method = state.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
||||
Content = objectJSON
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||
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;
|
||||
});
|
||||
return serverState;
|
||||
|
@ -81,24 +61,20 @@ namespace LeanCloud.Storage.Internal
|
|||
public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
|
||||
IList<IDictionary<string, IAVFieldOperation>> operationsList,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
CancellationToken cancellationToken) {
|
||||
|
||||
var requests = states
|
||||
.Zip(operationsList, (item, ops) => new AVCommand(
|
||||
item.ObjectId == null
|
||||
? string.Format("classes/{0}", Uri.EscapeDataString(item.ClassName))
|
||||
: string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
|
||||
method: item.ObjectId == null ? "POST" : "PUT",
|
||||
data: AVObject.ToJSONObjectForSaving(ops)))
|
||||
.Zip(operationsList, (item, ops) => new AVCommand {
|
||||
Path = item.ObjectId == null ? $"classes/{Uri.EscapeDataString(item.ClassName)}" : $"classes/{Uri.EscapeDataString(item.ClassName)}/{Uri.EscapeDataString(item.ObjectId)}",
|
||||
Method = item.ObjectId == null ? HttpMethod.Post : HttpMethod.Put,
|
||||
Content = AVObject.ToJSONObjectForSaving(ops)
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var batchTasks = ExecuteBatchRequests(requests, sessionToken, cancellationToken);
|
||||
var stateTasks = new List<Task<IObjectState>>();
|
||||
foreach (var task in batchTasks)
|
||||
{
|
||||
stateTasks.Add(task.OnSuccess(t =>
|
||||
{
|
||||
foreach (var task in batchTasks) {
|
||||
stateTasks.Add(task.OnSuccess(t => {
|
||||
return AVObjectCoder.Instance.Decode(t.Result, AVDecoder.Instance);
|
||||
}));
|
||||
}
|
||||
|
@ -108,27 +84,23 @@ namespace LeanCloud.Storage.Internal
|
|||
|
||||
public Task DeleteAsync(IObjectState state,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand(string.Format("classes/{0}/{1}",
|
||||
state.ClassName, state.ObjectId),
|
||||
method: "DELETE",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
CancellationToken cancellationToken) {
|
||||
var command = new AVCommand {
|
||||
Path = $"classes/{state.ClassName}/{state.ObjectId}",
|
||||
Method = HttpMethod.Delete
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
CancellationToken cancellationToken) {
|
||||
var requests = states
|
||||
.Where(item => item.ObjectId != null)
|
||||
.Select(item => new AVCommand(
|
||||
string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
|
||||
method: "DELETE",
|
||||
data: null))
|
||||
.Select(item => new AVCommand {
|
||||
Path = $"classes/{Uri.EscapeDataString(item.ClassName)}/{Uri.EscapeDataString(item.ObjectId)}",
|
||||
Method = HttpMethod.Delete
|
||||
})
|
||||
.ToList();
|
||||
return ExecuteBatchRequests(requests, sessionToken, cancellationToken).Cast<Task>().ToList();
|
||||
}
|
||||
|
@ -137,14 +109,12 @@ namespace LeanCloud.Storage.Internal
|
|||
private const int MaximumBatchSize = 50;
|
||||
internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<AVCommand> requests,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
CancellationToken cancellationToken) {
|
||||
var tasks = new List<Task<IDictionary<string, object>>>();
|
||||
int batchSize = requests.Count;
|
||||
|
||||
IEnumerable<AVCommand> remaining = requests;
|
||||
while (batchSize > MaximumBatchSize)
|
||||
{
|
||||
while (batchSize > MaximumBatchSize) {
|
||||
var process = remaining.Take(MaximumBatchSize).ToList();
|
||||
remaining = remaining.Skip(MaximumBatchSize);
|
||||
|
||||
|
@ -159,48 +129,40 @@ namespace LeanCloud.Storage.Internal
|
|||
|
||||
private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<AVCommand> requests,
|
||||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
CancellationToken cancellationToken) {
|
||||
var tasks = new List<Task<IDictionary<string, object>>>();
|
||||
int batchSize = requests.Count;
|
||||
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>>();
|
||||
tcss.Add(tcs);
|
||||
tasks.Add(tcs.Task);
|
||||
}
|
||||
|
||||
var encodedRequests = requests.Select(r =>
|
||||
{
|
||||
var encodedRequests = requests.Select(r => {
|
||||
var results = new Dictionary<string, object> {
|
||||
{ "method", r.Method },
|
||||
{ "path", r.Uri.AbsolutePath },
|
||||
{ "path", r.Path },
|
||||
};
|
||||
|
||||
if (r.Body != null)
|
||||
{
|
||||
results["body"] = r.Body;
|
||||
if (r.Content != null) {
|
||||
results["body"] = r.Content;
|
||||
}
|
||||
return results;
|
||||
}).Cast<object>().ToList();
|
||||
var command = new AVCommand("batch",
|
||||
method: "POST",
|
||||
sessionToken: sessionToken,
|
||||
data: new Dictionary<string, object> { { "requests", encodedRequests } });
|
||||
|
||||
commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||
{
|
||||
if (t.IsFaulted || t.IsCanceled)
|
||||
{
|
||||
foreach (var tcs in tcss)
|
||||
{
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
var command = new AVCommand {
|
||||
Path = "batch",
|
||||
Method = HttpMethod.Post,
|
||||
Content = new Dictionary<string, object> {
|
||||
{ "requests", encodedRequests }
|
||||
}
|
||||
};
|
||||
commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t => {
|
||||
if (t.IsFaulted || t.IsCanceled) {
|
||||
foreach (var tcs in tcss) {
|
||||
if (t.IsFaulted) {
|
||||
tcs.TrySetException(t.Exception);
|
||||
}
|
||||
else if (t.IsCanceled)
|
||||
{
|
||||
} else if (t.IsCanceled) {
|
||||
tcs.TrySetCanceled();
|
||||
}
|
||||
}
|
||||
|
@ -209,33 +171,25 @@ namespace LeanCloud.Storage.Internal
|
|||
|
||||
var resultsArray = Conversion.As<IList<object>>(t.Result.Item2["results"]);
|
||||
int resultLength = resultsArray.Count;
|
||||
if (resultLength != batchSize)
|
||||
{
|
||||
foreach (var tcs in tcss)
|
||||
{
|
||||
if (resultLength != batchSize) {
|
||||
foreach (var tcs in tcss) {
|
||||
tcs.TrySetException(new InvalidOperationException(
|
||||
"Batch command result count expected: " + batchSize + " but was: " + resultLength + "."));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < batchSize; ++i)
|
||||
{
|
||||
for (int i = 0; i < batchSize; ++i) {
|
||||
var result = resultsArray[i] as Dictionary<string, object>;
|
||||
var tcs = tcss[i];
|
||||
|
||||
if (result.ContainsKey("success"))
|
||||
{
|
||||
if (result.ContainsKey("success")) {
|
||||
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>;
|
||||
long errorCode = long.Parse(error["code"].ToString());
|
||||
tcs.TrySetException(new AVException((AVException.ErrorCode)errorCode, error["error"] as string));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
tcs.TrySetException(new InvalidOperationException(
|
||||
"Invalid batch command response."));
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LeanCloud.Storage.Internal;
|
||||
|
||||
namespace LeanCloud.Storage.Internal
|
||||
{
|
||||
|
@ -75,14 +74,10 @@ namespace LeanCloud.Storage.Internal
|
|||
string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var command = new AVCommand(string.Format("{0}?{1}",
|
||||
relativeUri,
|
||||
AVClient.BuildQueryString(parameters)),
|
||||
method: "GET",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = $"{relativeUri}?{AVClient.BuildQueryString(parameters)}",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
return t.Result.Item2;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud.Storage.Internal {
|
||||
public class AVSessionController : IAVSessionController {
|
||||
|
@ -13,31 +13,28 @@ namespace LeanCloud.Storage.Internal {
|
|||
}
|
||||
|
||||
public Task<IObjectState> GetSessionAsync(string sessionToken, CancellationToken cancellationToken) {
|
||||
var command = new AVCommand("sessions/me",
|
||||
method: "GET",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = "sessions/me",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||
});
|
||||
}
|
||||
|
||||
public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) {
|
||||
var command = new AVCommand("logout",
|
||||
method: "POST",
|
||||
sessionToken: sessionToken,
|
||||
data: new Dictionary<string, object>());
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = "logout",
|
||||
Method = HttpMethod.Post
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public Task<IObjectState> UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) {
|
||||
var command = new AVCommand("upgradeToRevocableSession",
|
||||
method: "POST",
|
||||
sessionToken: sessionToken,
|
||||
data: new Dictionary<string, object>());
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = "upgradeToRevocableSession",
|
||||
Method = HttpMethod.Post,
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t => {
|
||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud.Storage.Internal
|
||||
{
|
||||
|
@ -20,11 +20,11 @@ namespace LeanCloud.Storage.Internal
|
|||
CancellationToken cancellationToken)
|
||||
{
|
||||
var objectJSON = AVObject.ToJSONObjectForSaving(operations);
|
||||
|
||||
var command = new AVCommand("classes/_User",
|
||||
method: "POST",
|
||||
data: objectJSON);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = "classes/_User",
|
||||
Method = HttpMethod.Post,
|
||||
Content = objectJSON
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||
|
@ -49,11 +49,11 @@ namespace LeanCloud.Storage.Internal
|
|||
if (email != null) {
|
||||
data.Add("email", email);
|
||||
}
|
||||
|
||||
var command = new AVCommand("login",
|
||||
method: "POST",
|
||||
data: data);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = "login",
|
||||
Method = HttpMethod.Post,
|
||||
Content = data
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
var serverState = AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||
|
@ -73,12 +73,13 @@ namespace LeanCloud.Storage.Internal
|
|||
var authData = new Dictionary<string, object>();
|
||||
authData[authType] = data;
|
||||
var path = failOnNotExist ? "users?failOnNotExist=true" : "users";
|
||||
var command = new AVCommand(path,
|
||||
method: "POST",
|
||||
data: new Dictionary<string, object> {
|
||||
var command = new AVCommand {
|
||||
Path = path,
|
||||
Method = HttpMethod.Post,
|
||||
Content = new Dictionary<string, object> {
|
||||
{ "authData", authData}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
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)
|
||||
{
|
||||
var command = new AVCommand("users/me",
|
||||
method: "GET",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = "users/me",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
return AVObjectCoder.Instance.Decode(t.Result.Item2, AVDecoder.Instance);
|
||||
|
@ -105,22 +105,24 @@ namespace LeanCloud.Storage.Internal
|
|||
|
||||
public Task RequestPasswordResetAsync(string email, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand("requestPasswordReset",
|
||||
method: "POST",
|
||||
data: new Dictionary<string, object> {
|
||||
var command = new AVCommand {
|
||||
Path = "requestPasswordReset",
|
||||
Method = HttpMethod.Post,
|
||||
Content = new Dictionary<string, object> {
|
||||
{ "email", email}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public Task<IObjectState> LogInWithParametersAsync(string relativeUrl, IDictionary<string, object> data,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand(string.Format("{0}", relativeUrl),
|
||||
method: "POST",
|
||||
data: data);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = relativeUrl,
|
||||
Method = HttpMethod.Post,
|
||||
Content = data
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
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)
|
||||
{
|
||||
var command = new AVCommand(String.Format("users/{0}/updatePassword", userId),
|
||||
method: "PUT",
|
||||
sessionToken: sessionToken,
|
||||
data: new Dictionary<string, object> {
|
||||
{"old_password", oldPassword},
|
||||
{"new_password", newPassword},
|
||||
});
|
||||
var command = new AVCommand {
|
||||
Path = $"users/{userId}/updatePassword",
|
||||
Method = HttpMethod.Put,
|
||||
Content = new Dictionary<string, object> {
|
||||
{ "old_password", oldPassword },
|
||||
{ "new_password", newPassword },
|
||||
}
|
||||
};
|
||||
return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
public Task<IObjectState> RefreshSessionTokenAsync(string userId, string sessionToken,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand(String.Format("users/{0}/refreshSessionToken", userId),
|
||||
method: "PUT",
|
||||
sessionToken: sessionToken,
|
||||
data: null);
|
||||
var command = new AVCommand {
|
||||
Path = $"users/{userId}/refreshSessionToken",
|
||||
Method = HttpMethod.Put
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t =>
|
||||
{
|
||||
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;
|
||||
/// <summary>
|
||||
/// 当前 SDK 版本号
|
||||
|
@ -431,16 +437,6 @@ namespace LeanCloud
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
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)
|
||||
{
|
||||
|
@ -452,42 +448,5 @@ namespace LeanCloud
|
|||
var codeValue = (int)responseStatus;
|
||||
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.Tasks;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud {
|
||||
/// <summary>
|
||||
|
@ -77,37 +78,6 @@ namespace LeanCloud {
|
|||
}).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>
|
||||
|
@ -154,10 +124,11 @@ namespace LeanCloud {
|
|||
{
|
||||
strs.Add("TTL", ttl);
|
||||
}
|
||||
var command = new AVCommand("requestSmsCode",
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: strs);
|
||||
var command = new EngineCommand {
|
||||
Path = "requestSmsCode",
|
||||
Method = HttpMethod.Post,
|
||||
Content = strs
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -227,10 +198,11 @@ namespace LeanCloud {
|
|||
{
|
||||
strs.Add(key, env[key]);
|
||||
}
|
||||
var command = new AVCommand("requestSmsCode",
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: strs);
|
||||
var command = new EngineCommand {
|
||||
Path = "requestSmsCode",
|
||||
Method = HttpMethod.Post,
|
||||
Content = strs
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -248,17 +220,18 @@ namespace LeanCloud {
|
|||
{
|
||||
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 },
|
||||
{ "smsType", "voice" },
|
||||
{ "IDD","+86" }
|
||||
{ "IDD", "+86" }
|
||||
};
|
||||
|
||||
var command = new AVCommand("requestSmsCode",
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: strs);
|
||||
var command = new EngineCommand {
|
||||
Path = "requestSmsCode",
|
||||
Method = HttpMethod.Post,
|
||||
Content = body
|
||||
};
|
||||
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
|
@ -286,11 +259,9 @@ namespace LeanCloud {
|
|||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
public static Task<bool> VerifySmsCodeAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand("verifySmsCode/" + code.Trim() + "?mobilePhoneNumber=" + mobilePhoneNumber.Trim(),
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = $"verifySmsCode/{code.Trim()}?mobilePhoneNumber={mobilePhoneNumber.Trim()}",
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||
{
|
||||
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))
|
||||
{
|
||||
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 =>
|
||||
{
|
||||
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
||||
|
@ -355,12 +329,15 @@ namespace LeanCloud {
|
|||
/// <returns></returns>
|
||||
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_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 =>
|
||||
{
|
||||
if (!t.Result.Item2.ContainsKey("validate_token"))
|
||||
|
@ -376,11 +353,10 @@ namespace LeanCloud {
|
|||
/// <returns></returns>
|
||||
public static Task<IDictionary<string, object>> GetCustomParametersAsync(CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var command = new AVCommand(string.Format("statistics/apps/{0}/sendPolicy", AVClient.CurrentConfiguration.ApplicationId),
|
||||
method: "GET",
|
||||
sessionToken: null,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = $"statistics/apps/{AVClient.CurrentConfiguration.ApplicationId}/sendPolicy",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).OnSuccess(t =>
|
||||
{
|
||||
var settings = t.Result.Item2;
|
||||
|
@ -407,14 +383,13 @@ namespace LeanCloud {
|
|||
|
||||
public static Task<RealtimeSignature> RequestRealtimeSignatureAsync(AVUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var command = new AVCommand(string.Format("rtm/sign"),
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: new Dictionary<string, object>
|
||||
{
|
||||
{ "session_token", user.SessionToken },
|
||||
}
|
||||
);
|
||||
var command = new AVCommand {
|
||||
Path = "rtm/sign",
|
||||
Method = HttpMethod.Post,
|
||||
Content = new Dictionary<string, string> {
|
||||
{ "session_token", user.SessionToken }
|
||||
}
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t =>
|
||||
{
|
||||
var body = t.Result.Item2;
|
||||
|
@ -517,12 +492,11 @@ namespace LeanCloud {
|
|||
{
|
||||
var user = t.Result;
|
||||
var encodedParameters = Encode(parameters);
|
||||
var command = new AVCommand(
|
||||
string.Format("call/{0}", Uri.EscapeUriString(this.FunctionName)),
|
||||
method: "POST",
|
||||
sessionToken: user != null ? user.SessionToken : null,
|
||||
data: encodedParameters);
|
||||
|
||||
var command = new EngineCommand {
|
||||
Path = $"call/{Uri.EscapeUriString(FunctionName)}",
|
||||
Method = HttpMethod.Post,
|
||||
Content = encodedParameters
|
||||
};
|
||||
return AVClient.RunCommandAsync(command);
|
||||
|
||||
}).Unwrap().OnSuccess(s =>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -355,14 +355,18 @@ namespace LeanCloud
|
|||
};
|
||||
AVCommand cmd = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(this.ObjectId))
|
||||
{
|
||||
cmd = new AVCommand("files/" + this.ObjectId,
|
||||
method: "PUT", sessionToken: AVUser.CurrentSessionToken, data: strs);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = new AVCommand("files", method: "POST", sessionToken: AVUser.CurrentSessionToken, data: strs);
|
||||
if (!string.IsNullOrEmpty(this.ObjectId)) {
|
||||
cmd = new AVCommand {
|
||||
Path = $"files/{ObjectId}",
|
||||
Method = HttpMethod.Put,
|
||||
Content = strs
|
||||
};
|
||||
} else {
|
||||
cmd = new AVCommand {
|
||||
Path = "files",
|
||||
Method = HttpMethod.Post,
|
||||
Content = strs
|
||||
};
|
||||
}
|
||||
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(cmd).ContinueWith(t =>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud
|
||||
{
|
||||
|
@ -209,7 +208,7 @@ namespace LeanCloud
|
|||
}).Unwrap().OnSuccess(t =>
|
||||
{
|
||||
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)
|
||||
{
|
||||
var command = new AVCommand(queryString,
|
||||
method: "GET",
|
||||
sessionToken: AVUser.CurrentSessionToken,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = queryString,
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command, cancellationToken: CancellationToken.None).OnSuccess(t =>
|
||||
{
|
||||
var items = t.Result.Item2["results"] as IList<object>;
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
using LeanCloud.Storage.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -69,9 +67,10 @@ namespace LeanCloud
|
|||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
var command = new AVCommand(String.Format("users/me?session_token={0}", CurrentSessionToken),
|
||||
method: "GET",
|
||||
data: null);
|
||||
var command = new AVCommand {
|
||||
Path = $"users/me?session_token={CurrentSessionToken}",
|
||||
Method = HttpMethod.Get
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -297,10 +296,11 @@ namespace LeanCloud
|
|||
{
|
||||
data = this.EncodeForSaving(data);
|
||||
}
|
||||
var command = new AVCommand(string.Format("users/{0}/friendship/{1}", this.ObjectId, userObjectId),
|
||||
method: "POST",
|
||||
sessionToken: CurrentSessionToken,
|
||||
data: data);
|
||||
var command = new AVCommand {
|
||||
Path = $"users/{ObjectId}/friendship/{userObjectId}",
|
||||
Method = HttpMethod.Post,
|
||||
Content = data
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -314,10 +314,10 @@ namespace LeanCloud
|
|||
/// <returns></returns>
|
||||
public Task<bool> UnfollowAsync(string userObjectId)
|
||||
{
|
||||
var command = new AVCommand(string.Format("users/{0}/friendship/{1}", this.ObjectId, userObjectId),
|
||||
method: "DELETE",
|
||||
sessionToken: CurrentSessionToken,
|
||||
data: null);
|
||||
var command = new AVCommand {
|
||||
Path = $"users/{ObjectId}/friendship/{userObjectId}",
|
||||
Method = HttpMethod.Delete
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -1045,10 +1045,11 @@ namespace LeanCloud
|
|||
{
|
||||
strs.Add("validate_token", validateToken);
|
||||
}
|
||||
var command = new AVCommand("requestLoginSmsCode",
|
||||
method: "POST",
|
||||
sessionToken: CurrentSessionToken,
|
||||
data: strs);
|
||||
var command = new AVCommand {
|
||||
Path = "requestLoginSmsCode",
|
||||
Method = HttpMethod.Post,
|
||||
Content = strs
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -1183,10 +1184,11 @@ namespace LeanCloud
|
|||
{
|
||||
strs.Add("validate_token", validateToken);
|
||||
}
|
||||
var command = new AVCommand("requestPasswordResetBySmsCode",
|
||||
method: "POST",
|
||||
sessionToken: currentSessionToken,
|
||||
data: strs);
|
||||
var command = new AVCommand {
|
||||
Path = "requestPasswordResetBySmsCode",
|
||||
Method = HttpMethod.Post,
|
||||
Content = strs
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -1218,10 +1220,11 @@ namespace LeanCloud
|
|||
{
|
||||
{ "password", newPassword }
|
||||
};
|
||||
var command = new AVCommand("resetPasswordBySmsCode/" + smsCode,
|
||||
method: "PUT",
|
||||
sessionToken: currentSessionToken,
|
||||
data: strs);
|
||||
var command = new AVCommand {
|
||||
Path = $"resetPasswordBySmsCode/{smsCode}",
|
||||
Method = HttpMethod.Put,
|
||||
Content = strs
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -1278,10 +1281,11 @@ namespace LeanCloud
|
|||
{
|
||||
strs.Add("validate_token", validateToken);
|
||||
}
|
||||
var command = new AVCommand("requestMobilePhoneVerify",
|
||||
method: "POST",
|
||||
sessionToken: currentSessionToken,
|
||||
data: strs);
|
||||
var command = new AVCommand {
|
||||
Path = "requestMobilePhoneVerify",
|
||||
Method = HttpMethod.Post,
|
||||
Content = strs
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -1308,10 +1312,10 @@ namespace LeanCloud
|
|||
/// <returns></returns>
|
||||
public static Task<bool> VerifyMobilePhoneAsync(string code, string mobilePhoneNumber, CancellationToken cancellationToken)
|
||||
{
|
||||
var command = new AVCommand("verifyMobilePhone/" + code.Trim() + "?mobilePhoneNumber=" + mobilePhoneNumber.Trim(),
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: null);
|
||||
var command = new AVCommand {
|
||||
Path = $"verifyMobilePhone/{code.Trim()}?mobilePhoneNumber={mobilePhoneNumber.Trim()}",
|
||||
Method = HttpMethod.Post
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -1325,11 +1329,10 @@ namespace LeanCloud
|
|||
/// <returns></returns>
|
||||
public static Task<bool> VerifyMobilePhoneAsync(string code)
|
||||
{
|
||||
var command = new AVCommand("verifyMobilePhone/" + code.Trim(),
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: null);
|
||||
|
||||
var command = new AVCommand {
|
||||
Path = $"verifyMobilePhone/{code.Trim()}",
|
||||
Method = HttpMethod.Post
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
@ -1363,10 +1366,11 @@ namespace LeanCloud
|
|||
{
|
||||
{ "email", email }
|
||||
};
|
||||
var command = new AVCommand("requestEmailVerify",
|
||||
method: "POST",
|
||||
sessionToken: null,
|
||||
data: strs);
|
||||
var command = new AVCommand {
|
||||
Path = "requestEmailVerify",
|
||||
Method = HttpMethod.Post,
|
||||
Content = strs
|
||||
};
|
||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).ContinueWith(t =>
|
||||
{
|
||||
return AVClient.IsSuccessStatusCode(t.Result.Item1);
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using LeanCloud.Storage.Internal;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace LeanCloud {
|
||||
/// <summary>
|
||||
|
@ -153,7 +152,11 @@ namespace LeanCloud {
|
|||
{ "versionChangeInterval", versionChangeInterval.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 => {
|
||||
try {
|
||||
var leaderboard = Parse(t.Result.Item2);
|
||||
|
@ -211,7 +214,11 @@ namespace LeanCloud {
|
|||
if (overwrite) {
|
||||
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 => {
|
||||
try {
|
||||
List<AVStatistic> statisticList = new List<AVStatistic>();
|
||||
|
@ -242,7 +249,10 @@ namespace LeanCloud {
|
|||
path = string.Format("{0}?statistics={1}", path, names);
|
||||
}
|
||||
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 => {
|
||||
try {
|
||||
List<AVStatistic> statisticList = new List<AVStatistic>();
|
||||
|
@ -272,7 +282,10 @@ namespace LeanCloud {
|
|||
var path = string.Format("leaderboard/users/{0}/statistics", user.ObjectId);
|
||||
var names = string.Join(",", statisticNames.ToArray());
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -285,7 +298,10 @@ namespace LeanCloud {
|
|||
public Task<List<AVLeaderboardArchive>> GetArchives(int skip = 0, int limit = 10) {
|
||||
var path = string.Format("leaderboard/leaderboards/{0}/archives", StatisticName);
|
||||
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 => {
|
||||
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
|
||||
List<object> list = t.Result.Item2["results"] as List<object>;
|
||||
|
@ -342,7 +358,10 @@ namespace LeanCloud {
|
|||
var statistics = string.Join(",", includeStatistics.ToArray());
|
||||
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 => {
|
||||
try {
|
||||
List<AVRanking> rankingList = new List<AVRanking>();
|
||||
|
@ -389,7 +408,11 @@ namespace LeanCloud {
|
|||
|
||||
Task<IDictionary<string,object>> Update(Dictionary<string, object> data) {
|
||||
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 t.Result.Item2;
|
||||
});
|
||||
|
@ -401,7 +424,10 @@ namespace LeanCloud {
|
|||
/// <returns>排行榜对象</returns>
|
||||
public Task<AVLeaderboard> Fetch() {
|
||||
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 => {
|
||||
try {
|
||||
// 反序列化 Leaderboard 对象
|
||||
|
@ -419,7 +445,10 @@ namespace LeanCloud {
|
|||
/// <returns>排行榜对象</returns>
|
||||
public Task<AVLeaderboard> Reset() {
|
||||
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 => {
|
||||
try {
|
||||
Init(t.Result.Item2);
|
||||
|
@ -435,7 +464,10 @@ namespace LeanCloud {
|
|||
/// </summary>
|
||||
public Task Destroy() {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue