From f2ec04a3310c75e55cf73e506f665e4d0fb6e15c Mon Sep 17 00:00:00 2001 From: oneRain Date: Fri, 9 Aug 2019 12:27:35 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E8=A7=84=E8=8C=83=20http=20=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=20headers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Storage/Storage/Internal/Command/AVCommand.cs | 9 +- .../Internal/Command/AVCommandRunner.cs | 86 +++++++++-------- .../Storage/Internal/HttpClient/HttpClient.cs | 4 +- Storage/Storage/Public/AVClient.cs | 92 +++++++------------ 4 files changed, 91 insertions(+), 100 deletions(-) diff --git a/Storage/Storage/Internal/Command/AVCommand.cs b/Storage/Storage/Internal/Command/AVCommand.cs index 43a972f..5676e2d 100644 --- a/Storage/Storage/Internal/Command/AVCommand.cs +++ b/Storage/Storage/Internal/Command/AVCommand.cs @@ -25,7 +25,14 @@ namespace LeanCloud.Storage.Internal } public Dictionary Headers { - get; set; + get { + if (AVUser.CurrentUser != null) { + return new Dictionary { + { "X-LC-Session", AVUser.CurrentUser.SessionToken } + }; + } + return null; + } } public object Content { diff --git a/Storage/Storage/Internal/Command/AVCommandRunner.cs b/Storage/Storage/Internal/Command/AVCommandRunner.cs index 1411ac6..5c8d37e 100644 --- a/Storage/Storage/Internal/Command/AVCommandRunner.cs +++ b/Storage/Storage/Internal/Command/AVCommandRunner.cs @@ -6,6 +6,7 @@ using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using System.Text; +using System.Linq; using Newtonsoft.Json; namespace LeanCloud.Storage.Internal { @@ -13,9 +14,35 @@ namespace LeanCloud.Storage.Internal { /// Command Runner. /// public class AVCommandRunner { - public const string APPLICATION_JSON = "application/json"; + const string APPLICATION_JSON = "application/json"; + const string USE_PRODUCTION = "1"; + const string USE_DEVELOPMENT = "0"; - private readonly System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient(); + private readonly System.Net.Http.HttpClient httpClient; + + public AVCommandRunner() { + httpClient = new System.Net.Http.HttpClient(); + ProductHeaderValue product = new ProductHeaderValue(AVClient.Name, AVClient.Version); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(product)); + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(APPLICATION_JSON)); + + var conf = AVClient.CurrentConfiguration; + // App ID + httpClient.DefaultRequestHeaders.Add("X-LC-Id", conf.ApplicationId); + // App Signature + long timestamp = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds; + if (!string.IsNullOrEmpty(conf.MasterKey) && AVClient.UseMasterKey) { + string sign = MD5.GetMd5String(timestamp + conf.MasterKey); + httpClient.DefaultRequestHeaders.Add("X-LC-Sign", $"{sign},{timestamp},master"); + } else { + string sign = MD5.GetMd5String(timestamp + conf.ApplicationKey); + httpClient.DefaultRequestHeaders.Add("X-LC-Sign", $"{sign},{timestamp}"); + } + // TODO Session + + // Production + httpClient.DefaultRequestHeaders.Add("X-LC-Prod", AVClient.UseProduction ? USE_PRODUCTION : USE_DEVELOPMENT); + } /// /// @@ -30,21 +57,22 @@ namespace LeanCloud.Storage.Internal { IProgress downloadProgress = null, CancellationToken cancellationToken = default) { + string content = JsonConvert.SerializeObject(command.Content); var request = new HttpRequestMessage { RequestUri = command.Uri, Method = command.Method, - Content = new StringContent(JsonConvert.SerializeObject(command.Content)) + Content = new StringContent(content) }; - var headers = GetHeadersAsync(); - foreach (var header in headers) { - if (!string.IsNullOrEmpty(header.Value)) { + request.Content.Headers.ContentType = new MediaTypeHeaderValue(APPLICATION_JSON); + // 特殊 Headers + if (command.Headers != null) { + foreach (KeyValuePair header in command.Headers) { request.Headers.Add(header.Key, header.Value); } } - request.Content.Headers.ContentType = new MediaTypeHeaderValue(APPLICATION_JSON); + PrintRequest(httpClient, request, content); - PrintRequest(command, headers); var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); request.Dispose(); @@ -87,38 +115,22 @@ namespace LeanCloud.Storage.Internal { return new Tuple(responseCode, default); } - private const string revocableSessionTokenTrueValue = "1"; - - Dictionary GetHeadersAsync() { - var headers = new Dictionary(); - var installationId = AVPlugins.Instance.InstallationIdController.Get(); - headers.Add("X-LC-Installation-Id", installationId); - 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(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; - } - - static void PrintRequest(AVCommand request, Dictionary headers) { + static void PrintRequest(System.Net.Http.HttpClient client, HttpRequestMessage request, string content) { StringBuilder sb = new StringBuilder(); sb.AppendLine("=== HTTP Request Start ==="); - sb.AppendLine($"URL: {request.Uri}"); + sb.AppendLine($"URL: {request.RequestUri}"); sb.AppendLine($"Method: {request.Method}"); - sb.AppendLine($"Headers: {JsonConvert.SerializeObject(headers)}"); - sb.AppendLine($"Content: {JsonConvert.SerializeObject(request.Content)}"); + sb.AppendLine($"Headers: "); + foreach (var header in client.DefaultRequestHeaders) { + sb.AppendLine($"\t{header.Key}: {string.Join(",", header.Value.ToArray())}"); + } + foreach (var header in request.Headers) { + sb.AppendLine($"\t{header.Key}: {string.Join(",", header.Value.ToArray())}"); + } + foreach (var header in request.Content.Headers) { + sb.AppendLine($"\t{header.Key}: {string.Join(",", header.Value.ToArray())}"); + } + sb.AppendLine($"Content: {content}"); sb.AppendLine("=== HTTP Request End ==="); AVClient.PrintLog(sb.ToString()); } diff --git a/Storage/Storage/Internal/HttpClient/HttpClient.cs b/Storage/Storage/Internal/HttpClient/HttpClient.cs index ee941b9..b545737 100644 --- a/Storage/Storage/Internal/HttpClient/HttpClient.cs +++ b/Storage/Storage/Internal/HttpClient/HttpClient.cs @@ -29,8 +29,8 @@ namespace LeanCloud.Storage.Internal { public HttpClient() { client = new NetHttpClient(); - // TODO 设置版本号 - client.DefaultRequestHeaders.Add("User-Agent", "LeanCloud-dotNet-SDK/" + "2.0.0"); + // 设置版本号 + client.DefaultRequestHeaders.Add("User-Agent", $"LeanCloud-csharp-sdk-{AVClient.Version}"); } public HttpClient(NetHttpClient client) { diff --git a/Storage/Storage/Public/AVClient.cs b/Storage/Storage/Public/AVClient.cs index e148f44..9cf7b0b 100644 --- a/Storage/Storage/Public/AVClient.cs +++ b/Storage/Storage/Public/AVClient.cs @@ -11,14 +11,12 @@ using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; -namespace LeanCloud -{ +namespace LeanCloud { /// /// AVClient contains static functions that handle global /// configuration for the LeanCloud library. /// - public static class AVClient - { + public static class AVClient { public static readonly string[] DateFormatStrings = { // Official ISO format "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'", @@ -31,13 +29,11 @@ namespace LeanCloud /// /// Represents the configuration of the LeanCloud SDK. /// - public struct Configuration - { + public struct Configuration { /// /// 与 SDK 通讯的云端节点 /// - public enum AVRegion - { + public enum AVRegion { /// /// 默认值,LeanCloud 华北节点,同 Public_North_China /// @@ -81,8 +77,7 @@ namespace LeanCloud /// Any values set here will overwrite those that are automatically configured by /// any platform-specific migration library your app includes. /// - public struct VersionInformation - { + public struct VersionInformation { /// /// The build number of your app. /// @@ -110,10 +105,8 @@ namespace LeanCloud /// public AVRegion Region { get; set; } - internal int RegionValue - { - get - { + internal int RegionValue { + get { return (int)Region; } } @@ -178,29 +171,24 @@ namespace LeanCloud /// public static Configuration CurrentConfiguration { get; internal set; } - internal static Version Version - { - get - { - var assemblyName = new AssemblyName(typeof(AVClient).GetTypeInfo().Assembly.FullName); - return assemblyName.Version; - } - } - internal static string APIVersion { get { return "1.1"; } } + public static string Name { + get { + return "LeanCloud-CSharp-SDK"; + } + } + /// /// 当前 SDK 版本号 /// - public static string VersionString - { - get - { - return "net-v0.1.0"; + public static string Version { + get { + return "0.1.0"; } } @@ -214,10 +202,8 @@ namespace LeanCloud /// /// The .NET API Key provided in the LeanCloud dashboard. /// - public static void Initialize(string applicationId, string applicationKey) - { - Initialize(new Configuration - { + public static void Initialize(string applicationId, string applicationKey) { + Initialize(new Configuration { ApplicationId = applicationId, ApplicationKey = applicationKey }); @@ -229,16 +215,14 @@ namespace LeanCloud /// 启动日志打印 /// /// - public static void HttpLog(Action trace) - { + public static void HttpLog(Action trace) { LogTracker = trace; } /// /// 打印 HTTP 访问日志 /// /// - public static void PrintLog(string log) - { + public static void PrintLog(string log) { LogTracker?.Invoke(log); } @@ -262,8 +246,7 @@ namespace LeanCloud /// /// The configuration to initialize LeanCloud with. /// - public static void Initialize(Configuration configuration) - { + public static void Initialize(Configuration configuration) { Config(configuration); AVObject.RegisterSubclass(); @@ -271,15 +254,11 @@ namespace LeanCloud AVObject.RegisterSubclass(); } - internal static void Config(Configuration configuration) - { - lock (mutex) - { + internal static void Config(Configuration configuration) { + lock (mutex) { var nodeHash = configuration.ApplicationId.Split('-'); - if (nodeHash.Length > 1) - { - if (nodeHash[1].Trim() == "9Nh9j0Va") - { + if (nodeHash.Length > 1) { + if (nodeHash[1].Trim() == "9Nh9j0Va") { configuration.Region = Configuration.AVRegion.Public_East_China; } } @@ -288,8 +267,7 @@ namespace LeanCloud } } - internal static void Clear() - { + internal static void Clear() { AVPlugins.Instance.AppRouterController.Clear(); AVPlugins.Instance.Reset(); AVUser.ClearInMemoryUser(); @@ -299,16 +277,13 @@ namespace LeanCloud /// Switch app. /// /// Configuration. - public static void Switch(Configuration configuration) - { + public static void Switch(Configuration configuration) { Clear(); Initialize(configuration); } - public static void Switch(string applicationId, string applicationKey, Configuration.AVRegion region = Configuration.AVRegion.Public_North_China) - { - var configuration = new Configuration - { + public static void Switch(string applicationId, string applicationKey, Configuration.AVRegion region = Configuration.AVRegion.Public_North_China) { + var configuration = new Configuration { ApplicationId = applicationId, ApplicationKey = applicationKey, Region = region @@ -316,8 +291,7 @@ namespace LeanCloud Switch(configuration); } - public static string BuildQueryString(IDictionary parameters) - { + public static string BuildQueryString(IDictionary parameters) { return string.Join("&", (from pair in parameters let valueString = pair.Value as string select string.Format("{0}={1}", @@ -327,11 +301,9 @@ namespace LeanCloud .ToArray()); } - internal static IDictionary DecodeQueryString(string queryString) - { + internal static IDictionary DecodeQueryString(string queryString) { var dict = new Dictionary(); - foreach (var pair in queryString.Split('&')) - { + foreach (var pair in queryString.Split('&')) { var parts = pair.Split(new char[] { '=' }, 2); dict[parts[0]] = parts.Length == 2 ? Uri.UnescapeDataString(parts[1].Replace("+", " ")) : null; }