From 98d1d2325d515ef0e6bd0a59c961967e9b5224be Mon Sep 17 00:00:00 2001 From: David Date: Mon, 10 Aug 2020 16:12:22 +0200 Subject: Prepare plugin Api migration --- .../Extensions/ApiServiceCollectionExtensions.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs') diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 83d8fac5b..d25d1ae89 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -18,7 +18,10 @@ using Jellyfin.Api.Constants; using Jellyfin.Api.Controllers; using Jellyfin.Server.Formatters; using Jellyfin.Server.Models; +using MediaBrowser.Common; using MediaBrowser.Common.Json; +using MediaBrowser.Common.Plugins; +using MediaBrowser.Controller; using MediaBrowser.Model.Entities; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; @@ -135,10 +138,11 @@ namespace Jellyfin.Server.Extensions /// /// The service collection. /// The base url for the API. + /// The application host. /// The MVC builder. - public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl) + public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl, IApplicationHost applicationHost) { - return serviceCollection + IMvcBuilder mvcBuilder = serviceCollection .AddCors(options => { options.AddPolicy(ServerCorsPolicy.DefaultPolicyName, ServerCorsPolicy.DefaultPolicy); @@ -177,6 +181,16 @@ namespace Jellyfin.Server.Extensions options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy; }) .AddControllersAsServices(); + + if (applicationHost.Plugins != null) + { + foreach (IPlugin plugin in applicationHost.Plugins) + { + mvcBuilder.AddApplicationPart(plugin.GetType().Assembly); + } + } + + return mvcBuilder; } /// -- cgit v1.2.3 From 9e95fe8f9d402ec178024be962115abd6033fb51 Mon Sep 17 00:00:00 2001 From: David Date: Tue, 11 Aug 2020 17:04:11 +0200 Subject: Add plugin assemblies to mvc builder --- Emby.Server.Implementations/ApplicationHost.cs | 25 +++++++++++++++++++++- .../Extensions/ApiServiceCollectionExtensions.cs | 14 ++++-------- MediaBrowser.Common/IApplicationHost.cs | 7 ++++++ 3 files changed, 35 insertions(+), 11 deletions(-) (limited to 'Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0201ed7a3..438f4384f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -53,7 +53,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; -using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Collections; @@ -98,6 +97,7 @@ using MediaBrowser.Providers.Plugins.TheTvdb; using MediaBrowser.Providers.Subtitles; using MediaBrowser.XbmcMetadata.Providers; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Prometheus.DotNetRuntime; @@ -1385,6 +1385,29 @@ namespace Emby.Server.Implementations _plugins = list.ToArray(); } + public IEnumerable GetApiPluginAssemblies() + { + var assemblies = new List(); + try + { + var types = _allConcreteTypes + .Where(i => typeof(ControllerBase).IsAssignableFrom(i)) + // .Select(i => ActivatorUtilities.CreateInstance(ServiceProvider, i)) + .ToArray(); + + foreach (var variable in types) + { + assemblies.Add(variable.Assembly); + } + } + catch (Exception ex) + { + // ignore + } + + return assemblies; + } + public virtual void LaunchUrl(string url) { if (!CanLaunchWebBrowser) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index d25d1ae89..13c2d6055 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -20,8 +20,6 @@ using Jellyfin.Server.Formatters; using Jellyfin.Server.Models; using MediaBrowser.Common; using MediaBrowser.Common.Json; -using MediaBrowser.Common.Plugins; -using MediaBrowser.Controller; using MediaBrowser.Model.Entities; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; @@ -179,18 +177,14 @@ namespace Jellyfin.Server.Extensions // From JsonDefaults.PascalCase options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy; - }) - .AddControllersAsServices(); + }); - if (applicationHost.Plugins != null) + foreach (Assembly pluginAssembly in applicationHost.GetApiPluginAssemblies()) { - foreach (IPlugin plugin in applicationHost.Plugins) - { - mvcBuilder.AddApplicationPart(plugin.GetType().Assembly); - } + mvcBuilder.AddApplicationPart(pluginAssembly); } - return mvcBuilder; + return mvcBuilder.AddControllersAsServices(); } /// diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index e8d9282e4..bdbd469bd 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; using System.Threading.Tasks; using MediaBrowser.Common.Plugins; using Microsoft.Extensions.DependencyInjection; @@ -76,6 +77,12 @@ namespace MediaBrowser.Common /// The plugins. IReadOnlyList Plugins { get; } + /// + /// Gets all plugin assemblies which implement a custom rest api. + /// + /// An containing the plugin assemblies. + IEnumerable GetApiPluginAssemblies(); + /// /// Notifies the pending restart. /// -- cgit v1.2.3 From 340f83c3f5e0f42e7b02be0e4402e2039f8fe734 Mon Sep 17 00:00:00 2001 From: crobibero Date: Sun, 23 Aug 2020 07:48:12 -0600 Subject: Ignore null json values --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 3 +++ Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 2 ++ MediaBrowser.Common/Json/JsonDefaults.cs | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 5bf740cfc..48e2f5d4a 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -90,6 +90,9 @@ namespace Emby.Server.Implementations.Data _typeMapper = new TypeMapper(); _jsonOptions = JsonDefaults.GetOptions(); + // GetItem throws NotSupportedException with this enabled, so hardcode false. + _jsonOptions.IgnoreNullValues = false; + DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 2e2bfea68..1f9fc7078 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -168,6 +168,8 @@ namespace Jellyfin.Server.Extensions // From JsonDefaults options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented; + options.JsonSerializerOptions.IgnoreNullValues = jsonOptions.IgnoreNullValues; + options.JsonSerializerOptions.Converters.Clear(); foreach (var converter in jsonOptions.Converters) { diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 0a661934e..891715b3d 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -24,7 +24,8 @@ namespace MediaBrowser.Common.Json var options = new JsonSerializerOptions { ReadCommentHandling = JsonCommentHandling.Disallow, - WriteIndented = false + WriteIndented = false, + IgnoreNullValues = true }; options.Converters.Add(new JsonGuidConverter()); -- cgit v1.2.3 From 5f64ab02a01f35f2bc2429cdee56973e77048fa5 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 25 Aug 2020 07:33:58 -0600 Subject: bump System.Text.Json --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 3 --- Jellyfin.Api/Controllers/PluginsController.cs | 8 ++++++-- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 6 +++++- Jellyfin.Api/Jellyfin.Api.csproj | 1 + Jellyfin.Data/Jellyfin.Data.csproj | 1 + Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 1 + .../Migrations/Routines/MigrateDisplayPreferencesDb.cs | 5 +++++ Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs | 7 ++++++- MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs | 5 +++++ MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs | 5 +++++ MediaBrowser.Common/Json/JsonDefaults.cs | 2 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 +- tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj | 1 + 14 files changed, 39 insertions(+), 10 deletions(-) (limited to 'Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 48e2f5d4a..5bf740cfc 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -90,9 +90,6 @@ namespace Emby.Server.Implementations.Data _typeMapper = new TypeMapper(); _jsonOptions = JsonDefaults.GetOptions(); - // GetItem throws NotSupportedException with this enabled, so hardcode false. - _jsonOptions.IgnoreNullValues = false; - DbFilePath = Path.Combine(_config.ApplicationPaths.DataPath, "library.db"); } diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index b2f34680b..a82f2621a 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -120,10 +120,14 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var configuration = (BasePluginConfiguration)await JsonSerializer.DeserializeAsync(Request.Body, plugin.ConfigurationType, _serializerOptions) + var configuration = (BasePluginConfiguration?)await JsonSerializer.DeserializeAsync(Request.Body, plugin.ConfigurationType, _serializerOptions) .ConfigureAwait(false); - plugin.UpdateConfiguration(configuration); + if (configuration != null) + { + plugin.UpdateConfiguration(configuration); + } + return NoContent(); } diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index d2d1855a4..3a736d1e8 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -127,7 +127,11 @@ namespace Jellyfin.Api.Helpers { // Since we're going to be setting properties on MediaSourceInfos that come out of _mediaSourceManager, we should clone it // Should we move this directly into MediaSourceManager? - result.MediaSources = JsonSerializer.Deserialize(JsonSerializer.SerializeToUtf8Bytes(mediaSources)); + var mediaSourcesClone = JsonSerializer.Deserialize(JsonSerializer.SerializeToUtf8Bytes(mediaSources)); + if (mediaSourcesClone != null) + { + result.MediaSources = mediaSourcesClone; + } result.PlaySessionId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); } diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 24bc07b66..7eb0ba007 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -19,6 +19,7 @@ + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 43b838cc1..bf5833ae4 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -22,6 +22,7 @@ + diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 1f9fc7078..ddbe0edb7 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -168,7 +168,7 @@ namespace Jellyfin.Server.Extensions // From JsonDefaults options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented; - options.JsonSerializerOptions.IgnoreNullValues = jsonOptions.IgnoreNullValues; + options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition; options.JsonSerializerOptions.Converters.Clear(); foreach (var converter in jsonOptions.Converters) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 7541707d9..4cc51a098 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -54,6 +54,7 @@ + diff --git a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs index b15ccf01e..2e5f0cc05 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateDisplayPreferencesDb.cs @@ -81,6 +81,11 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var result in results) { var dto = JsonSerializer.Deserialize(result[3].ToString(), _jsonOptions); + if (dto is null) + { + continue; + } + var chromecastVersion = dto.CustomPrefs.TryGetValue("chromecastVersion", out var version) ? chromecastDict[version] : ChromecastVersion.Stable; diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index 274e6ab73..6cd6d1f82 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -74,7 +74,12 @@ namespace Jellyfin.Server.Migrations.Routines foreach (var entry in queryResult) { - UserMockup mockup = JsonSerializer.Deserialize(entry[2].ToBlob(), JsonDefaults.GetOptions()); + UserMockup? mockup = JsonSerializer.Deserialize(entry[2].ToBlob(), JsonDefaults.GetOptions()); + if (mockup is null) + { + continue; + } + var userDataDir = Path.Combine(_paths.UserConfigurationDirectoryPath, mockup.Name); var config = File.Exists(Path.Combine(userDataDir, "config.xml")) diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs index c1660fe76..9db44d626 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs @@ -14,6 +14,11 @@ namespace MediaBrowser.Common.Json.Converters /// public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { + if (reader.TokenType == JsonTokenType.Null) + { + return null; + } + if (reader.TokenType == JsonTokenType.String) { ReadOnlySpan span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs index 53e5f6e9d..a9cdc23d7 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs +++ b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs @@ -21,6 +21,11 @@ namespace MediaBrowser.Common.Json.Converters /// Parsed value. public override long? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) { + if (reader.TokenType == JsonTokenType.Null) + { + return null; + } + if (reader.TokenType == JsonTokenType.String) { // try to parse number directly from bytes diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index 891715b3d..b46ecffc7 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Common.Json { ReadCommentHandling = JsonCommentHandling.Disallow, WriteIndented = false, - IgnoreNullValues = true + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault }; options.Converters.Add(new JsonGuidConverter()); diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 902e29b20..a2aef948b 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -25,7 +25,7 @@ - + diff --git a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj index a4ef10648..9d797e8ee 100644 --- a/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj +++ b/tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj @@ -10,6 +10,7 @@ + -- cgit v1.2.3 From 8b96881aa1667495c78b0955321254da0dc5a22f Mon Sep 17 00:00:00 2001 From: crobibero Date: Wed, 26 Aug 2020 08:22:48 -0600 Subject: Clean up json Converters --- .../Extensions/ApiServiceCollectionExtensions.cs | 1 + .../Json/Converters/JsonDoubleConverter.cs | 56 --------------- .../Json/Converters/JsonInt32Converter.cs | 40 ----------- .../Json/Converters/JsonInt64Converter.cs | 56 --------------- .../JsonNonStringKeyDictionaryConverter.cs | 82 ---------------------- .../JsonNonStringKeyDictionaryConverterFactory.cs | 59 ---------------- .../Json/Converters/JsonNullableInt32Converter.cs | 60 ---------------- .../Json/Converters/JsonNullableInt64Converter.cs | 75 -------------------- MediaBrowser.Common/Json/JsonDefaults.cs | 9 +-- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 ++ .../Probing/MediaStreamInfo.cs | 1 - .../FFprobeParserTests.cs | 3 +- 12 files changed, 11 insertions(+), 437 deletions(-) delete mode 100644 MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs delete mode 100644 MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs (limited to 'Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs') diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index ddbe0edb7..0fd599cfc 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -169,6 +169,7 @@ namespace Jellyfin.Server.Extensions options.JsonSerializerOptions.ReadCommentHandling = jsonOptions.ReadCommentHandling; options.JsonSerializerOptions.WriteIndented = jsonOptions.WriteIndented; options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition; + options.JsonSerializerOptions.NumberHandling = jsonOptions.NumberHandling; options.JsonSerializerOptions.Converters.Clear(); foreach (var converter in jsonOptions.Converters) diff --git a/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs b/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs deleted file mode 100644 index 56c0ecbe9..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonDoubleConverter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Globalization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Double to String JSON converter. - /// Web client send quoted doubles. - /// - public class JsonDoubleConverter : JsonConverter - { - /// - /// Read JSON string as double. - /// - /// . - /// Type. - /// Options. - /// Parsed value. - public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - // try to parse number directly from bytes - var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out double number, out var bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters - if (double.TryParse(reader.GetString(), out number)) - { - return number; - } - } - - // fallback to default handling - return reader.GetDouble(); - } - - /// - /// Write double to JSON string. - /// - /// . - /// Value to write. - /// Options. - public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs deleted file mode 100644 index 7ed9d6766..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonInt32Converter.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Converts a int32 object or value to/from JSON. - /// - public class JsonInt32Converter : JsonConverter - { - /// - public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - ReadOnlySpan span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - if (int.TryParse(reader.GetString(), out number)) - { - return number; - } - } - - return reader.GetInt32(); - } - - /// - public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs deleted file mode 100644 index 427f1fa7e..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonInt64Converter.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Globalization; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Parse JSON string as long. - /// Javascript does not support 64-bit integers. - /// - public class JsonInt64Converter : JsonConverter - { - /// - /// Read JSON string as int64. - /// - /// . - /// Type. - /// Options. - /// Parsed value. - public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.String) - { - // try to parse number directly from bytes - var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters - if (long.TryParse(reader.GetString(), out number)) - { - return number; - } - } - - // fallback to default handling - return reader.GetInt64(); - } - - /// - /// Write long to JSON long. - /// - /// . - /// Value to write. - /// Options. - public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options) - { - writer.WriteNumberValue(value); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs b/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs deleted file mode 100644 index 8053461f0..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverter.cs +++ /dev/null @@ -1,82 +0,0 @@ -#nullable enable - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Converter for Dictionaries without string key. - /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys. - /// - /// Type of key. - /// Type of value. - internal sealed class JsonNonStringKeyDictionaryConverter : JsonConverter> - { - /// - /// Read JSON. - /// - /// The Utf8JsonReader. - /// The type to convert. - /// The json serializer options. - /// Typed dictionary. - /// Dictionary key type not supported. - public override IDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var convertedType = typeof(Dictionary<,>).MakeGenericType(typeof(string), typeToConvert.GenericTypeArguments[1]); - var value = JsonSerializer.Deserialize(ref reader, convertedType, options); - var instance = (Dictionary)Activator.CreateInstance( - typeToConvert, - BindingFlags.Instance | BindingFlags.Public, - null, - null, - CultureInfo.CurrentCulture); - var enumerator = (IEnumerator)convertedType.GetMethod("GetEnumerator")!.Invoke(value, null); - var parse = typeof(TKey).GetMethod( - "Parse", - 0, - BindingFlags.Public | BindingFlags.Static, - null, - CallingConventions.Any, - new[] { typeof(string) }, - null); - if (parse == null) - { - throw new NotSupportedException($"{typeof(TKey)} as TKey in IDictionary is not supported."); - } - - while (enumerator.MoveNext()) - { - var element = (KeyValuePair)enumerator.Current; - instance.Add((TKey)parse.Invoke(null, new[] { (object?)element.Key }), element.Value); - } - - return instance; - } - - /// - /// Write dictionary as Json. - /// - /// The Utf8JsonWriter. - /// The dictionary value. - /// The Json serializer options. - public override void Write(Utf8JsonWriter writer, IDictionary value, JsonSerializerOptions options) - { - var convertedDictionary = new Dictionary(value.Count); - foreach (var (k, v) in value) - { - if (k != null) - { - convertedDictionary[k.ToString()] = v; - } - } - - JsonSerializer.Serialize(writer, convertedDictionary, options); - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs b/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs deleted file mode 100644 index 52f360740..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNonStringKeyDictionaryConverterFactory.cs +++ /dev/null @@ -1,59 +0,0 @@ -#nullable enable - -using System; -using System.Collections; -using System.Globalization; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// https://github.com/dotnet/runtime/issues/30524#issuecomment-524619972. - /// TODO This can be removed when System.Text.Json supports Dictionaries with non-string keys. - /// - internal sealed class JsonNonStringKeyDictionaryConverterFactory : JsonConverterFactory - { - /// - /// Only convert objects that implement IDictionary and do not have string keys. - /// - /// Type convert. - /// Conversion ability. - public override bool CanConvert(Type typeToConvert) - { - if (!typeToConvert.IsGenericType) - { - return false; - } - - // Let built in converter handle string keys - if (typeToConvert.GenericTypeArguments[0] == typeof(string)) - { - return false; - } - - // Only support objects that implement IDictionary - return typeToConvert.GetInterface(nameof(IDictionary)) != null; - } - - /// - /// Create converter for generic dictionary type. - /// - /// Type to convert. - /// Json serializer options. - /// JsonConverter for given type. - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var converterType = typeof(JsonNonStringKeyDictionaryConverter<,>) - .MakeGenericType(typeToConvert.GenericTypeArguments[0], typeToConvert.GenericTypeArguments[1]); - var converter = (JsonConverter)Activator.CreateInstance( - converterType, - BindingFlags.Instance | BindingFlags.Public, - null, - null, - CultureInfo.CurrentCulture); - return converter; - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs deleted file mode 100644 index 9db44d626..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt32Converter.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Converts a nullable int32 object or value to/from JSON. - /// - public class JsonNullableInt32Converter : JsonConverter - { - /// - public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Null) - { - return null; - } - - if (reader.TokenType == JsonTokenType.String) - { - ReadOnlySpan span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out int number, out int bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - var stringValue = reader.GetString().AsSpan(); - - // value is null or empty, just return null. - if (stringValue.IsEmpty) - { - return null; - } - - if (int.TryParse(stringValue, out number)) - { - return number; - } - } - - return reader.GetInt32(); - } - - /// - public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options) - { - if (value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteNumberValue(value.Value); - } - } - } -} diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs b/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs deleted file mode 100644 index a9cdc23d7..000000000 --- a/MediaBrowser.Common/Json/Converters/JsonNullableInt64Converter.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace MediaBrowser.Common.Json.Converters -{ - /// - /// Parse JSON string as nullable long. - /// Javascript does not support 64-bit integers. - /// - public class JsonNullableInt64Converter : JsonConverter - { - /// - /// Read JSON string as int64. - /// - /// . - /// Type. - /// Options. - /// Parsed value. - public override long? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) - { - if (reader.TokenType == JsonTokenType.Null) - { - return null; - } - - if (reader.TokenType == JsonTokenType.String) - { - // try to parse number directly from bytes - var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; - if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed) - { - return number; - } - - var stringValue = reader.GetString().AsSpan(); - - // value is null or empty, just return null. - if (stringValue.IsEmpty) - { - return null; - } - - // try to parse from a string if the above failed, this covers cases with other escaped/UTF characters - if (long.TryParse(stringValue, out number)) - { - return number; - } - } - - // fallback to default handling - return reader.GetInt64(); - } - - /// - /// Write long to JSON long. - /// - /// . - /// Value to write. - /// Options. - public override void Write(Utf8JsonWriter writer, long? value, JsonSerializerOptions options) - { - if (value is null) - { - writer.WriteNullValue(); - } - else - { - writer.WriteNumberValue(value.Value); - } - } - } -} diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs index b46ecffc7..9d30927db 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/MediaBrowser.Common/Json/JsonDefaults.cs @@ -25,17 +25,12 @@ namespace MediaBrowser.Common.Json { ReadCommentHandling = JsonCommentHandling.Disallow, WriteIndented = false, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + NumberHandling = JsonNumberHandling.AllowReadingFromString }; options.Converters.Add(new JsonGuidConverter()); - options.Converters.Add(new JsonInt32Converter()); - options.Converters.Add(new JsonNullableInt32Converter()); options.Converters.Add(new JsonStringEnumConverter()); - options.Converters.Add(new JsonNonStringKeyDictionaryConverterFactory()); - options.Converters.Add(new JsonInt64Converter()); - options.Converters.Add(new JsonNullableInt64Converter()); - options.Converters.Add(new JsonDoubleConverter()); return options; } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 9d01da40f..5a3a9185d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -12,6 +12,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; @@ -54,6 +55,9 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly object _runningProcessesLock = new object(); private readonly List _runningProcesses = new List(); + // MediaEncoder is registered as a Singleton + private readonly JsonSerializerOptions _jsonSerializerOptions; + private List _encoders = new List(); private List _decoders = new List(); private List _hwaccels = new List(); @@ -75,6 +79,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _localization = localization; _encodingHelperFactory = encodingHelperFactory; _startupOptionFFmpegPath = config.GetValue(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty; + _jsonSerializerOptions = JsonDefaults.GetOptions(); } private EncodingHelper EncodingHelper => _encodingHelperFactory.Value; @@ -414,6 +419,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { result = await JsonSerializer.DeserializeAsync( process.StandardOutput.BaseStream, + _jsonSerializerOptions, cancellationToken: cancellationToken).ConfigureAwait(false); } catch diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs index 8996d3b09..b7b23deff 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfo.cs @@ -133,7 +133,6 @@ namespace MediaBrowser.MediaEncoding.Probing /// /// The bits_per_raw_sample. [JsonPropertyName("bits_per_raw_sample")] - [JsonConverter(typeof(JsonInt32Converter))] public int BitsPerRawSample { get; set; } /// diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 2032f6cec..c39ef0ce9 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -1,6 +1,7 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; +using MediaBrowser.Common.Json; using MediaBrowser.MediaEncoding.Probing; using Xunit; @@ -15,7 +16,7 @@ namespace Jellyfin.MediaEncoding.Tests var path = Path.Join("Test Data", fileName); using (var stream = File.OpenRead(path)) { - await JsonSerializer.DeserializeAsync(stream).ConfigureAwait(false); + await JsonSerializer.DeserializeAsync(stream, JsonDefaults.GetOptions()).ConfigureAwait(false); } } } -- cgit v1.2.3 From 3453b654441b4ef91dd8c2e22ffa535081b87857 Mon Sep 17 00:00:00 2001 From: Cromefire_ Date: Sun, 30 Aug 2020 00:44:33 +0200 Subject: Fixed wrong openapi auth header value --- Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs') diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 0fd599cfc..f0ae9fbfc 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -197,7 +197,7 @@ namespace Jellyfin.Server.Extensions { Type = SecuritySchemeType.ApiKey, In = ParameterLocation.Header, - Name = "X-Emby-Token", + Name = "X-Emby-Authorization", Description = "API key header parameter" }); -- cgit v1.2.3 From 7f79f2ee0e1fe3b5f0edb22677df9f9235d883fa Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Mon, 31 Aug 2020 17:53:55 +0200 Subject: Use .Distinct on assembly --- Emby.Server.Implementations/ApplicationHost.cs | 10 ++++++---- Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 6 +++--- Jellyfin.Server/Startup.cs | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) (limited to 'Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 62c2e55c2..d2f016f7d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1387,15 +1387,17 @@ namespace Emby.Server.Implementations public IEnumerable GetApiPluginAssemblies() { - var types = _allConcreteTypes + var assemblies = _allConcreteTypes .Where(i => typeof(ControllerBase).IsAssignableFrom(i)) + .Select(i => i.Assembly) .Distinct(); - foreach (var type in types) + foreach (var assembly in assemblies) { - Logger.LogDebug("Found API endpoints in plugin {name}", type.Assembly.FullName); - yield return type.Assembly; + Logger.LogDebug("Found API endpoints in plugin {name}", assembly.FullName); } + + return assemblies; } public virtual void LaunchUrl(string url) diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 13c2d6055..1c872efe0 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -136,9 +136,9 @@ namespace Jellyfin.Server.Extensions /// /// The service collection. /// The base url for the API. - /// The application host. + /// An IEnumberable containing all plugin assemblies with API controllers. /// The MVC builder. - public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl, IApplicationHost applicationHost) + public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl, IEnumerable pluginAssemblies) { IMvcBuilder mvcBuilder = serviceCollection .AddCors(options => @@ -179,7 +179,7 @@ namespace Jellyfin.Server.Extensions options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy; }); - foreach (Assembly pluginAssembly in applicationHost.GetApiPluginAssemblies()) + foreach (Assembly pluginAssembly in pluginAssemblies) { mvcBuilder.AddApplicationPart(pluginAssembly); } diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 7c54334d1..ef255fb60 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -41,7 +41,7 @@ namespace Jellyfin.Server { services.AddResponseCompression(); services.AddHttpContextAccessor(); - services.AddJellyfinApi(_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/'), _applicationHost); + services.AddJellyfinApi(_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/'), _applicationHost.GetApiPluginAssemblies()); services.AddJellyfinApiSwagger(); -- cgit v1.2.3