diff options
| -rw-r--r-- | Emby.Server.Implementations/ApplicationHost.cs | 15 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Emby.Server.Implementations.csproj | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/ImageController.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/LibraryStructureController.cs | 12 | ||||
| -rw-r--r-- | Jellyfin.Api/Models/LibraryStructureDto/AddVirtualFolderDto.cs (renamed from Jellyfin.Api/Models/LibraryStructureDto/LibraryOptionsDto.cs) | 6 | ||||
| -rw-r--r-- | Jellyfin.Api/Models/LibraryStructureDto/UpdateLibraryOptionsDto.cs | 21 | ||||
| -rw-r--r-- | Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs | 18 | ||||
| -rw-r--r-- | Jellyfin.Server/Startup.cs | 26 | ||||
| -rw-r--r-- | MediaBrowser.Common/IApplicationHost.cs | 7 | ||||
| -rw-r--r-- | MediaBrowser.Common/Net/DefaultHttpClientHandler.cs | 20 | ||||
| -rw-r--r-- | MediaBrowser.Common/Net/NamedClient.cs | 18 |
11 files changed, 129 insertions, 22 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index cb63cc85e..a2d6e2c9e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -97,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; @@ -1393,6 +1394,20 @@ namespace Emby.Server.Implementations _plugins = list.ToArray(); } + public IEnumerable<Assembly> GetApiPluginAssemblies() + { + var assemblies = _allConcreteTypes + .Where(i => typeof(ControllerBase).IsAssignableFrom(i)) + .Select(i => i.Assembly) + .Distinct(); + + foreach (var assembly in assemblies) + { + Logger.LogDebug("Found API endpoints in plugin {name}", assembly.FullName); + yield return assembly; + } + } + public virtual void LaunchUrl(string url) { if (!CanLaunchWebBrowser) diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 60564f700..56fc57327 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -22,7 +22,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="IPNetwork2" Version="2.5.211" /> + <PackageReference Include="IPNetwork2" Version="2.5.224" /> <PackageReference Include="Jellyfin.XmlTv" Version="10.6.2" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" /> <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" /> @@ -37,7 +37,7 @@ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.6" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" /> <PackageReference Include="Mono.Nat" Version="2.0.2" /> - <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" /> + <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.4.0" /> <PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" /> <PackageReference Include="sharpcompress" Version="0.26.0" /> <PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" /> diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index ca9c2fa46..a204fe35c 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -1281,9 +1281,9 @@ namespace Jellyfin.Api.Controllers Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", new CultureInfo("en-US", false))); // if the image was not modified since "ifModifiedSinceHeader"-header, return a HTTP status code 304 not modified - if (!(dateImageModified > ifModifiedSinceHeader)) + if (!(dateImageModified > ifModifiedSinceHeader) && cacheDuration.HasValue) { - if (ifModifiedSinceHeader.Add(cacheDuration!.Value) < DateTime.UtcNow) + if (ifModifiedSinceHeader.Add(cacheDuration.Value) < DateTime.UtcNow) { Response.StatusCode = StatusCodes.Status304NotModified; return new ContentResult(); diff --git a/Jellyfin.Api/Controllers/LibraryStructureController.cs b/Jellyfin.Api/Controllers/LibraryStructureController.cs index cdab4f356..d290e3c5b 100644 --- a/Jellyfin.Api/Controllers/LibraryStructureController.cs +++ b/Jellyfin.Api/Controllers/LibraryStructureController.cs @@ -76,7 +76,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? name, [FromQuery] string? collectionType, [FromQuery] string[] paths, - [FromBody] LibraryOptionsDto? libraryOptionsDto, + [FromBody] AddVirtualFolderDto? libraryOptionsDto, [FromQuery] bool refreshLibrary = false) { var libraryOptions = libraryOptionsDto?.LibraryOptions ?? new LibraryOptions(); @@ -312,19 +312,17 @@ namespace Jellyfin.Api.Controllers /// <summary> /// Update library options. /// </summary> - /// <param name="id">The library name.</param> - /// <param name="libraryOptions">The library options.</param> + /// <param name="request">The library name and options.</param> /// <response code="204">Library updated.</response> /// <returns>A <see cref="NoContentResult"/>.</returns> [HttpPost("LibraryOptions")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult UpdateLibraryOptions( - [FromQuery] string? id, - [FromBody] LibraryOptions? libraryOptions) + [FromBody] UpdateLibraryOptionsDto request) { - var collectionFolder = (CollectionFolder)_libraryManager.GetItemById(id); + var collectionFolder = (CollectionFolder)_libraryManager.GetItemById(request.Id); - collectionFolder.UpdateLibraryOptions(libraryOptions); + collectionFolder.UpdateLibraryOptions(request.LibraryOptions); return NoContent(); } } diff --git a/Jellyfin.Api/Models/LibraryStructureDto/LibraryOptionsDto.cs b/Jellyfin.Api/Models/LibraryStructureDto/AddVirtualFolderDto.cs index a13cb90db..ab68d5223 100644 --- a/Jellyfin.Api/Models/LibraryStructureDto/LibraryOptionsDto.cs +++ b/Jellyfin.Api/Models/LibraryStructureDto/AddVirtualFolderDto.cs @@ -3,13 +3,13 @@ namespace Jellyfin.Api.Models.LibraryStructureDto { /// <summary> - /// Library options dto. + /// Add virtual folder dto. /// </summary> - public class LibraryOptionsDto + public class AddVirtualFolderDto { /// <summary> /// Gets or sets library options. /// </summary> public LibraryOptions? LibraryOptions { get; set; } } -}
\ No newline at end of file +} diff --git a/Jellyfin.Api/Models/LibraryStructureDto/UpdateLibraryOptionsDto.cs b/Jellyfin.Api/Models/LibraryStructureDto/UpdateLibraryOptionsDto.cs new file mode 100644 index 000000000..c78ed51f7 --- /dev/null +++ b/Jellyfin.Api/Models/LibraryStructureDto/UpdateLibraryOptionsDto.cs @@ -0,0 +1,21 @@ +using System; +using MediaBrowser.Model.Configuration; + +namespace Jellyfin.Api.Models.LibraryStructureDto +{ + /// <summary> + /// Update library options dto. + /// </summary> + public class UpdateLibraryOptionsDto + { + /// <summary> + /// Gets or sets the library item id. + /// </summary> + public Guid Id { get; set; } + + /// <summary> + /// Gets or sets library options. + /// </summary> + public LibraryOptions? LibraryOptions { get; set; } + } +} diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 0fd599cfc..0160a05f9 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -18,6 +18,7 @@ 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.Model.Entities; using Microsoft.AspNetCore.Authentication; @@ -135,10 +136,11 @@ namespace Jellyfin.Server.Extensions /// </summary> /// <param name="serviceCollection">The service collection.</param> /// <param name="baseUrl">The base url for the API.</param> + /// <param name="pluginAssemblies">An IEnumberable containing all plugin assemblies with API controllers.</param> /// <returns>The MVC builder.</returns> - public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl) + public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl, IEnumerable<Assembly> pluginAssemblies) { - return serviceCollection + IMvcBuilder mvcBuilder = serviceCollection .AddCors(options => { options.AddPolicy(ServerCorsPolicy.DefaultPolicyName, ServerCorsPolicy.DefaultPolicy); @@ -179,8 +181,14 @@ namespace Jellyfin.Server.Extensions // From JsonDefaults.PascalCase options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy; - }) - .AddControllersAsServices(); + }); + + foreach (Assembly pluginAssembly in pluginAssemblies) + { + mvcBuilder.AddApplicationPart(pluginAssembly); + } + + return mvcBuilder.AddControllersAsServices(); } /// <summary> @@ -197,7 +205,7 @@ namespace Jellyfin.Server.Extensions { Type = SecuritySchemeType.ApiKey, In = ParameterLocation.Header, - Name = "X-Emby-Token", + Name = "X-Emby-Authorization", Description = "API key header parameter" }); diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index d0dd183c6..cbc1c040c 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -1,9 +1,12 @@ using System; using System.ComponentModel; +using System.Net.Http.Headers; using Jellyfin.Api.TypeConverters; using Jellyfin.Server.Extensions; using Jellyfin.Server.Middleware; using Jellyfin.Server.Models; +using MediaBrowser.Common; +using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using Microsoft.AspNetCore.Builder; @@ -20,14 +23,17 @@ namespace Jellyfin.Server public class Startup { private readonly IServerConfigurationManager _serverConfigurationManager; + private readonly IApplicationHost _applicationHost; /// <summary> /// Initializes a new instance of the <see cref="Startup" /> class. /// </summary> /// <param name="serverConfigurationManager">The server configuration manager.</param> - public Startup(IServerConfigurationManager serverConfigurationManager) + /// <param name="applicationHost">The application host.</param> + public Startup(IServerConfigurationManager serverConfigurationManager, IApplicationHost applicationHost) { _serverConfigurationManager = serverConfigurationManager; + _applicationHost = applicationHost; } /// <summary> @@ -38,7 +44,7 @@ namespace Jellyfin.Server { services.AddResponseCompression(); services.AddHttpContextAccessor(); - services.AddJellyfinApi(_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/')); + services.AddJellyfinApi(_serverConfigurationManager.Configuration.BaseUrl.TrimStart('/'), _applicationHost.GetApiPluginAssemblies()); services.AddJellyfinApiSwagger(); @@ -46,7 +52,21 @@ namespace Jellyfin.Server services.AddCustomAuthentication(); services.AddJellyfinApiAuthorization(); - services.AddHttpClient(); + + var productHeader = new ProductInfoHeaderValue(_applicationHost.Name.Replace(' ', '-'), _applicationHost.ApplicationVersionString); + services + .AddHttpClient(NamedClient.Default, c => + { + c.DefaultRequestHeaders.UserAgent.Add(productHeader); + }) + .ConfigurePrimaryHttpMessageHandler(x => new DefaultHttpClientHandler()); + + services.AddHttpClient(NamedClient.MusicBrainz, c => + { + c.DefaultRequestHeaders.UserAgent.Add(productHeader); + c.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue($"({_applicationHost.ApplicationUserAgentAddress})")); + }) + .ConfigurePrimaryHttpMessageHandler(x => new DefaultHttpClientHandler()); } /// <summary> diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 7a76be722..849037ac4 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; @@ -77,6 +78,12 @@ namespace MediaBrowser.Common IReadOnlyList<IPlugin> Plugins { get; } /// <summary> + /// Gets all plugin assemblies which implement a custom rest api. + /// </summary> + /// <returns>An <see cref="IEnumerable{Assembly}"/> containing the plugin assemblies.</returns> + IEnumerable<Assembly> GetApiPluginAssemblies(); + + /// <summary> /// Notifies the pending restart. /// </summary> void NotifyPendingRestart(); diff --git a/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs b/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs new file mode 100644 index 000000000..e189d6e70 --- /dev/null +++ b/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs @@ -0,0 +1,20 @@ +using System.Net; +using System.Net.Http; + +namespace MediaBrowser.Common.Net +{ + /// <summary> + /// Default http client handler. + /// </summary> + public class DefaultHttpClientHandler : HttpClientHandler + { + /// <summary> + /// Initializes a new instance of the <see cref="DefaultHttpClientHandler"/> class. + /// </summary> + public DefaultHttpClientHandler() + { + // TODO change to DecompressionMethods.All with .NET5 + AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; + } + } +} diff --git a/MediaBrowser.Common/Net/NamedClient.cs b/MediaBrowser.Common/Net/NamedClient.cs new file mode 100644 index 000000000..0f6161c32 --- /dev/null +++ b/MediaBrowser.Common/Net/NamedClient.cs @@ -0,0 +1,18 @@ +namespace MediaBrowser.Common.Net +{ + /// <summary> + /// Registered http client names. + /// </summary> + public static class NamedClient + { + /// <summary> + /// Gets the value for the default named http client. + /// </summary> + public const string Default = nameof(Default); + + /// <summary> + /// Gets the value for the MusicBrainz named http client. + /// </summary> + public const string MusicBrainz = nameof(MusicBrainz); + } +} |
