chore: 重构网络模块

oneRain 2019-07-31 15:10:39 +08:00
parent fdfec81181
commit d19f389e2a
13 changed files with 241 additions and 202 deletions

View File

@ -1,7 +1,6 @@
using NUnit.Framework;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
using LeanCloud;
namespace LeanCloudTests {
@ -16,7 +15,6 @@ namespace LeanCloudTests {
}
[Test]
[AsyncStateMachine(typeof(ObjectControllerTests))]
public async Task TestSave() {
TestContext.Out.WriteLine($"before at {Thread.CurrentThread.ManagedThreadId}");
var obj = AVObject.Create("Foo");
@ -26,7 +24,6 @@ namespace LeanCloudTests {
Assert.NotNull(obj.ObjectId);
Assert.NotNull(obj.CreatedAt);
Assert.NotNull(obj.UpdatedAt);
await Task.Delay(10000);
}
}
}

View File

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Net.Http;
namespace LeanCloud.Storage.Internal
{
@ -43,7 +44,13 @@ namespace LeanCloud.Storage.Internal
string appId = AVClient.CurrentConfiguration.ApplicationId;
string url = string.Format("https://app-router.leancloud.cn/2/route?appId={0}", appId);
var ret = await AVClient.HttpGetAsync(new Uri(url));
var request = new HttpRequest {
Uri = new Uri(url),
Method = HttpMethod.Get,
Headers = null,
Data = null
};
var ret = await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
if (ret.Item1 != HttpStatusCode.OK) {
throw new AVException(AVException.ErrorCode.ConnectionFailed, "can not reach router.", null);
}

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Text;
using LeanCloud.Storage.Internal;
using System.Linq;
using System.Net.Http;
namespace LeanCloud.Storage.Internal
{
@ -14,105 +15,154 @@ namespace LeanCloud.Storage.Internal
public class AVCommand : HttpRequest
{
public IDictionary<string, object> DataObject { get; private set; }
public override Stream Data
{
get
{
if (base.Data != null)
{
return base.Data;
}
return base.Data = (DataObject != null
? new MemoryStream(Encoding.UTF8.GetBytes(Json.Encode(DataObject)))
: null);
public object Body {
get; set;
}
public override Stream Data {
get {
return new MemoryStream(Encoding.UTF8.GetBytes(Json.Encode(Body)));
}
set { base.Data = value; }
}
public AVCommand(string relativeUri,
string method,
string sessionToken = null,
IList<KeyValuePair<string, string>> headers = null,
IDictionary<string, object> data = null) : this(relativeUri: relativeUri,
method: method,
sessionToken: sessionToken,
headers: headers,
stream: null,
contentType: data != null ? "application/json" : null)
{
DataObject = data;
}
public AVCommand(string relativeUri,
string method,
string sessionToken = null,
IList<KeyValuePair<string, string>> headers = null,
Stream stream = null,
string contentType = 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") || relativeUri.StartsWith("installations"))
{
if (relativeUri.StartsWith("push") || relativeUri.StartsWith("installations")) {
Uri = new Uri(string.Format(urlTemplate, state.PushServer, apiVersion, relativeUri));
if (configuration.PushServer != null)
{
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"))
{
} 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)
{
if (configuration.StatsServer != null) {
Uri = new Uri(string.Format("{0}{1}/{2}", configuration.StatsServer, apiVersion, relativeUri));
}
}
else if (relativeUri.StartsWith("functions") || relativeUri.StartsWith("call"))
{
} else if (relativeUri.StartsWith("functions") || relativeUri.StartsWith("call")) {
Uri = new Uri(string.Format(urlTemplate, state.EngineServer, apiVersion, relativeUri));
if (configuration.EngineServer != null)
{
if (configuration.EngineServer != null) {
Uri = new Uri(string.Format("{0}{1}/{2}", configuration.EngineServer, apiVersion, relativeUri));
}
}
else
{
} else {
Uri = new Uri(string.Format(urlTemplate, state.ApiServer, apiVersion, relativeUri));
if (configuration.ApiServer != null)
{
if (configuration.ApiServer != null) {
Uri = new Uri(string.Format("{0}{1}/{2}", configuration.ApiServer, apiVersion, relativeUri));
}
}
Method = method;
Data = stream;
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))
{
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));
}
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.DataObject = other.DataObject;
this.Headers = new List<KeyValuePair<string, string>>(other.Headers);
this.Data = other.Data;
this.Body = other.Data;
}
}
}

View File

@ -35,7 +35,7 @@ namespace LeanCloud.Storage.Internal
/// <param name="downloadProgress"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(AVCommand command,
public Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(HttpRequest command,
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
CancellationToken cancellationToken = default(CancellationToken))
@ -99,11 +99,11 @@ namespace LeanCloud.Storage.Internal
}
private const string revocableSessionTokenTrueValue = "1";
private Task<AVCommand> PrepareCommand(AVCommand command)
private Task<HttpRequest> PrepareCommand(HttpRequest command)
{
AVCommand newCommand = new AVCommand(command);
HttpRequest newCommand = command;
Task<AVCommand> installationIdTask = installationIdController.GetAsync().ContinueWith(t =>
Task<HttpRequest> installationIdTask = installationIdController.GetAsync().ContinueWith(t =>
{
newCommand.Headers.Add(new KeyValuePair<string, string>("X-LC-Installation-Id", t.Result.ToString()));
return newCommand;

View File

@ -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(AVCommand command,
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> RunCommandAsync(HttpRequest command,
IProgress<AVUploadProgressEventArgs> uploadProgress = null,
IProgress<AVDownloadProgressEventArgs> downloadProgress = null,
CancellationToken cancellationToken = default(CancellationToken));

View File

@ -4,6 +4,7 @@ using System.Threading;
using System.Threading.Tasks;
using LeanCloud.Storage.Internal;
using System.Net;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
@ -32,55 +33,36 @@ namespace LeanCloud.Storage.Internal
/// <param name="sessionToken">Session token.</param>
/// <param name="progress">Progress.</param>
/// <param name="cancellationToken">Cancellation token.</param>
public virtual Task<FileState> SaveAsync(FileState state,
Stream dataStream,
String sessionToken,
IProgress<AVUploadProgressEventArgs> progress,
CancellationToken cancellationToken = default(CancellationToken))
{
if (state.Url != null)
{
public virtual async Task<FileState> SaveAsync(FileState state,
Stream dataStream,
String sessionToken,
IProgress<AVUploadProgressEventArgs> progress,
CancellationToken cancellationToken = default(CancellationToken)) {
if (state.Url != null) {
// !isDirty
return Task<FileState>.FromResult(state);
return state;
}
if (cancellationToken.IsCancellationRequested)
{
var tcs = new TaskCompletionSource<FileState>();
tcs.TrySetCanceled();
return tcs.Task;
if (cancellationToken.IsCancellationRequested) {
return null;
}
var oldPosition = dataStream.Position;
var command = new AVCommand("files/" + state.Name,
method: "POST",
sessionToken: sessionToken,
contentType: state.MimeType,
stream: dataStream);
return commandRunner.RunCommandAsync(command,
uploadProgress: progress,
cancellationToken: cancellationToken).OnSuccess(uploadTask =>
{
var result = uploadTask.Result;
var jsonData = result.Item2;
cancellationToken.ThrowIfCancellationRequested();
return new FileState
{
Name = jsonData["name"] as string,
Url = new Uri(jsonData["url"] as string, UriKind.Absolute),
MimeType = state.MimeType
};
}).ContinueWith(t =>
{
// Rewind the stream on failure or cancellation (if possible)
if ((t.IsFaulted || t.IsCanceled) && dataStream.CanSeek)
{
dataStream.Seek(oldPosition, SeekOrigin.Begin);
}
return t;
}).Unwrap();
var request = new HttpRequest {
Uri = new Uri("files/" + state.Name),
Method = HttpMethod.Post,
Headers = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("Content-Type", state.MimeType)
}
};
var ret = await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
var jsonData = Json.Parse(ret.Item2) as Dictionary<string, object>;
return new FileState {
Name = jsonData["name"] as string,
Url = new Uri(jsonData["url"] as string, UriKind.Absolute),
MimeType = state.MimeType
};
}
public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken)
{

View File

@ -4,6 +4,7 @@ using System.Threading;
using System.IO;
using LeanCloud.Storage.Internal;
using System.Collections.Generic;
using System.Net.Http;
namespace LeanCloud.Storage.Internal
{
@ -40,15 +41,18 @@ namespace LeanCloud.Storage.Internal
});
}
internal Task<FileState> PutFile(FileState state, string uploadUrl, Stream dataStream)
internal async Task<FileState> PutFile(FileState state, string uploadUrl, Stream dataStream)
{
IList<KeyValuePair<string, string>> makeBlockHeaders = new List<KeyValuePair<string, string>>();
makeBlockHeaders.Add(new KeyValuePair<string, string>("Content-Type", state.MimeType));
return AVClient.RequestAsync(new Uri(uploadUrl), "PUT", makeBlockHeaders, dataStream, state.MimeType, CancellationToken.None).OnSuccess(t =>
{
return state;
});
var request = new HttpRequest {
Uri = new Uri(uploadUrl),
Method = HttpMethod.Put,
Headers = makeBlockHeaders,
Data = dataStream
};
await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
return state;
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -159,7 +160,7 @@ namespace LeanCloud.Storage.Internal
return HexStringFromBytes(hashBytes);
}
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> PostToQCloud(
async Task<Tuple<HttpStatusCode, IDictionary<string, object>>> PostToQCloud(
Dictionary<string, object> body,
byte[] sliceFile,
CancellationToken cancellationToken)
@ -174,14 +175,15 @@ namespace LeanCloud.Storage.Internal
sliceHeaders.Add(new KeyValuePair<string, string>("Content-Type", contentType));
var rtn = AVClient.RequestAsync(new Uri(this.uploadUrl), "POST", sliceHeaders, tempStream, null, cancellationToken).OnSuccess(_ =>
{
var dic = AVClient.ReponseResolve(_.Result, CancellationToken.None);
return dic;
});
return rtn;
var request = new HttpRequest {
Uri = new Uri(this.uploadUrl),
Method = HttpMethod.Post,
Headers = sliceHeaders,
Data = tempStream
};
var ret = await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
var result = new Tuple<HttpStatusCode, IDictionary<string, object>>(ret.Item1, Json.Parse(ret.Item2) as Dictionary<string, object>);
return result;
}
public static Stream HttpUploadFile(byte[] file, string fileName, out string contentType, out long contentLength, IDictionary<string, object> nvc)
{

View File

@ -6,6 +6,7 @@ using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
namespace LeanCloud.Storage.Internal
{
@ -173,20 +174,32 @@ namespace LeanCloud.Storage.Internal
return makeBlockHeaders;
}
Task<Tuple<HttpStatusCode, string>> MakeBlock(FileState state, byte[] firstChunkBinary, long blcokSize = 4194304)
{
async Task<Tuple<HttpStatusCode, string>> MakeBlock(FileState state, byte[] firstChunkBinary, long blcokSize = 4194304) {
MemoryStream firstChunkData = new MemoryStream(firstChunkBinary, 0, firstChunkBinary.Length);
return AVClient.RequestAsync(new Uri(new Uri(UP_HOST) + string.Format("mkblk/{0}", blcokSize)), "POST", GetQiniuRequestHeaders(state), firstChunkData, "application/octet-stream", CancellationToken.None);
var headers = GetQiniuRequestHeaders(state);
headers.Add(new KeyValuePair<string, string>("Content-Type", "application/octet-stream"));
var request = new HttpRequest {
Uri = new Uri(new Uri(UP_HOST) + string.Format("mkblk/{0}", blcokSize)),
Method = HttpMethod.Post,
Headers = headers,
Data = firstChunkData
};
return await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
}
Task<Tuple<HttpStatusCode, string>> PutChunk(FileState state, byte[] chunkBinary, string LastChunkctx, long currentChunkOffsetInBlock)
{
async Task<Tuple<HttpStatusCode, string>> PutChunk(FileState state, byte[] chunkBinary, string LastChunkctx, long currentChunkOffsetInBlock) {
MemoryStream chunkData = new MemoryStream(chunkBinary, 0, chunkBinary.Length);
return AVClient.RequestAsync(new Uri(new Uri(UP_HOST) + string.Format("bput/{0}/{1}", LastChunkctx,
currentChunkOffsetInBlock)), "POST",
GetQiniuRequestHeaders(state), chunkData,
"application/octet-stream", CancellationToken.None);
var request = new HttpRequest {
Uri = new Uri(new Uri(UP_HOST) + string.Format("bput/{0}/{1}", LastChunkctx, currentChunkOffsetInBlock)),
Method = HttpMethod.Post,
Headers = GetQiniuRequestHeaders(state),
Data = chunkData
};
var ret = await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
return ret;
}
internal Task<Tuple<HttpStatusCode, string>> QiniuMakeFile(FileState state, Stream dataStream, string upToken, string key, long fsize, string[] ctxes, CancellationToken cancellationToken)
internal async Task<Tuple<HttpStatusCode, string>> QiniuMakeFile(FileState state, Stream dataStream, string upToken, string key, long fsize, string[] ctxes, CancellationToken cancellationToken)
{
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.AppendFormat("{0}/mkfile/{1}", UP_HOST, fsize);
@ -208,6 +221,7 @@ namespace LeanCloud.Storage.Internal
string authHead = "UpToken " + upToken;
headers.Add(new KeyValuePair<string, string>("Authorization", authHead));
headers.Add(new KeyValuePair<string, string>("Content-Type", "text/plain"));
int proCount = ctxes.Length;
Stream body = new MemoryStream();
@ -221,13 +235,14 @@ namespace LeanCloud.Storage.Internal
}
}
body.Seek(0, SeekOrigin.Begin);
var rtn = AVClient.RequestAsync(new Uri(urlBuilder.ToString()), "POST", headers, body, "text/plain", cancellationToken).OnSuccess(_ =>
{
var dic = AVClient.ReponseResolve(_.Result, CancellationToken.None);
return _.Result;
});
return rtn;
var request = new HttpRequest {
Uri = new Uri(urlBuilder.ToString()),
Method = HttpMethod.Post,
Headers = headers,
Data = body
};
var ret = await AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, CancellationToken.None);
return ret;
}
internal void MergeFromJSON(FileState state, IDictionary<string, object> jsonData)
{

View File

@ -41,18 +41,17 @@ namespace LeanCloud.Storage.Internal {
IProgress<AVUploadProgressEventArgs> uploadProgress,
IProgress<AVDownloadProgressEventArgs> downloadProgress,
CancellationToken cancellationToken) {
HttpMethod httpMethod = new HttpMethod(httpRequest.Method);
HttpMethod httpMethod = httpRequest.Method;
HttpRequestMessage message = new HttpRequestMessage(httpMethod, httpRequest.Uri);
// Fill in zero-length data if method is post.
Stream data = httpRequest.Data;
if (httpRequest.Data == null && httpRequest.Method.ToLower().Equals("post")) {
data = new MemoryStream(new byte[0]);
if (httpRequest.Data == null && httpRequest.Method == HttpMethod.Post) {
message.Content = new StreamContent(new MemoryStream(new byte[0]));
}
if (data != null) {
message.Content = new StreamContent(data);
if (httpRequest.Data != null) {
message.Content = new StreamContent(httpRequest.Data);
}
if (httpRequest.Headers != null) {
@ -74,6 +73,7 @@ namespace LeanCloud.Storage.Internal {
uploadProgress?.Report(new AVUploadProgressEventArgs { Progress = 0 });
var response = await client.SendAsync(message, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
uploadProgress?.Report(new AVUploadProgressEventArgs { Progress = 1 });
message.Dispose();
var resultString = await response.Content.ReadAsStringAsync();
response.Dispose();

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
namespace LeanCloud.Storage.Internal
{
@ -10,16 +11,12 @@ namespace LeanCloud.Storage.Internal
public class HttpRequest
{
public Uri Uri { get; set; }
public IList<KeyValuePair<string, string>> Headers { get; set; }
/// <summary>
/// Data stream to be uploaded.
/// </summary>
public virtual Stream Data { get; set; }
// HttpMethod
public HttpMethod Method { get; set; }
/// <summary>
/// HTTP method. One of <c>DELETE</c>, <c>GET</c>, <c>HEAD</c>, <c>POST</c> or <c>PUT</c>
/// </summary>
public string Method { get; set; }
public virtual Stream Data { get; set; }
}
}

View File

@ -16,7 +16,7 @@ namespace LeanCloud
/// AVClient contains static functions that handle global
/// configuration for the LeanCloud library.
/// </summary>
public static partial class AVClient
public static class AVClient
{
public static readonly string[] DateFormatStrings = {
// Official ISO format
@ -367,37 +367,37 @@ namespace LeanCloud
return Json.Encode(jsonData);
}
public static Task<Tuple<HttpStatusCode, string>> HttpGetAsync(Uri uri)
{
return RequestAsync(uri, "GET", null, body: null, contentType: null, cancellationToken: CancellationToken.None);
}
//public static Task<Tuple<HttpStatusCode, string>> HttpGetAsync(Uri uri)
//{
// return RequestAsync(uri, "GET", null, body: null, contentType: null, cancellationToken: CancellationToken.None);
//}
public static Task<Tuple<HttpStatusCode, string>> RequestAsync(Uri uri, string method, IList<KeyValuePair<string, string>> headers, IDictionary<string, object> body, string contentType, CancellationToken cancellationToken)
{
var dataStream = body != null ? new MemoryStream(Encoding.UTF8.GetBytes(Json.Encode(body))) : null;
return AVClient.RequestAsync(uri, method, headers, dataStream, contentType, cancellationToken);
//return AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, cancellationToken);
}
//public static Task<Tuple<HttpStatusCode, string>> RequestAsync(Uri uri, string method, IList<KeyValuePair<string, string>> headers, IDictionary<string, object> body, string contentType, CancellationToken cancellationToken)
//{
// var dataStream = body != null ? new MemoryStream(Encoding.UTF8.GetBytes(Json.Encode(body))) : null;
// return AVClient.RequestAsync(uri, method, headers, dataStream, contentType, cancellationToken);
// //return AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, cancellationToken);
//}
public static Task<Tuple<HttpStatusCode, string>> RequestAsync(Uri uri, string method, IList<KeyValuePair<string, string>> headers, Stream data, string contentType, CancellationToken cancellationToken)
{
HttpRequest request = new HttpRequest()
{
Data = data != null ? data : null,
Headers = headers,
Method = method,
Uri = uri
};
return AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, cancellationToken).OnSuccess(t =>
{
var response = t.Result;
var contentString = response.Item2;
int responseCode = (int)response.Item1;
var responseLog = responseCode + ";" + contentString;
PrintLog(responseLog);
return response;
});
}
//public static Task<Tuple<HttpStatusCode, string>> RequestAsync(Uri uri, string method, IList<KeyValuePair<string, string>> headers, Stream data, string contentType, CancellationToken cancellationToken)
//{
// HttpRequest request = new HttpRequest()
// {
// Data = data != null ? data : null,
// Headers = headers,
// Method = method,
// Uri = uri
// };
// return AVPlugins.Instance.HttpClient.ExecuteAsync(request, null, null, cancellationToken).OnSuccess(t =>
// {
// var response = t.Result;
// var contentString = response.Item2;
// int responseCode = (int)response.Item1;
// var responseLog = responseCode + ";" + contentString;
// PrintLog(responseLog);
// return response;
// });
//}
internal static Tuple<HttpStatusCode, IDictionary<string, object>> ReponseResolve(Tuple<HttpStatusCode, string> response, CancellationToken cancellationToken)
{
@ -477,21 +477,8 @@ namespace LeanCloud
try
{
if (request is AVCommand)
{
var command = (AVCommand)request;
if (command.DataObject != null)
{
var bodyLog = "Body:" + Json.Encode(command.DataObject);
sb.AppendLine(bodyLog);
}
}
else
{
StreamReader reader = new StreamReader(request.Data);
string bodyLog = reader.ReadToEnd();
sb.AppendLine(bodyLog);
}
var bodyLog = "Body:" + Json.Encode(request.Data);
sb.AppendLine(bodyLog);
}
catch (Exception)
{

View File

@ -211,9 +211,7 @@ namespace LeanCloud {
if (overwrite) {
path = string.Format("{0}?overwrite=1", path);
}
var dataStr = Json.Encode(data);
var dataStream = new MemoryStream(Encoding.UTF8.GetBytes(dataStr));
var command = new AVCommand(path, "POST", contentType: "application/json", sessionToken: user.SessionToken, stream: dataStream);
var command = new AVCommand(path, "POST", user.SessionToken, data: data);
return AVPlugins.Instance.CommandRunner.RunCommandAsync(command).OnSuccess(t => {
try {
List<AVStatistic> statisticList = new List<AVStatistic>();