diff --git a/.gitignore b/.gitignore index 0c7bef2..1d3454a 100644 --- a/.gitignore +++ b/.gitignore @@ -259,4 +259,4 @@ paket-files/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc -/src/Kyse.AspNetCore.StaticLibrary/Properties/PublishProfiles/Local.pubxml +/src/*/Properties/PublishProfiles/Local.pubxml diff --git a/Kyse.AspNetCore.StaticLibrary.sln b/Kyse.AspNetCore.StaticLibrary.sln index 52a0e90..15a9cf4 100644 --- a/Kyse.AspNetCore.StaticLibrary.sln +++ b/Kyse.AspNetCore.StaticLibrary.sln @@ -6,9 +6,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kyse.AspNetCore.StaticLibra EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68390E87-984C-4887-AD19-1DD41C49110B}" ProjectSection(SolutionItems) = preProject + src\common.props = src\common.props README.md = README.md EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kyse.AspNetCore.StaticLibrary.Abstractions", "src\Kyse.AspNetCore.StaticLibrary.Abstractions\Kyse.AspNetCore.StaticLibrary.Abstractions.csproj", "{770F83D8-C6C1-47BC-BE6C-983BC9C67F28}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -31,6 +34,18 @@ Global {309EE5C7-C0EC-41BB-87EA-82FA835D29E7}.Release|x64.Build.0 = Release|Any CPU {309EE5C7-C0EC-41BB-87EA-82FA835D29E7}.Release|x86.ActiveCfg = Release|Any CPU {309EE5C7-C0EC-41BB-87EA-82FA835D29E7}.Release|x86.Build.0 = Release|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Debug|Any CPU.Build.0 = Debug|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Debug|x64.ActiveCfg = Debug|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Debug|x64.Build.0 = Debug|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Debug|x86.ActiveCfg = Debug|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Debug|x86.Build.0 = Debug|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Release|Any CPU.ActiveCfg = Release|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Release|Any CPU.Build.0 = Release|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Release|x64.ActiveCfg = Release|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Release|x64.Build.0 = Release|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Release|x86.ActiveCfg = Release|Any CPU + {770F83D8-C6C1-47BC-BE6C-983BC9C67F28}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 871eb9f..3e71978 100644 --- a/README.md +++ b/README.md @@ -124,10 +124,3 @@ However, there are a few more added options avaialable to control authentication - AllowAnonymous - Set to true to allow anonymous access to the libraries expoesd by this middleware. - AuthenticationSchemes - Specify an Authentication Scheme to use for authenticating the request. > If not specified, all defined authentication schemes will be checked until one authenticates with a ClaimsPrincipal. - -## Todo & Thoughts -- Switch Invoke to async to allow authorizeasync calls since authorize requirements could be hitting a database backend. -- Might be worth adding MapWhen to UseStaticLibrary extension against the root library path to prevent unneeded calls to our middleware code. -- Move interfaces to an abstractions package to remove nuget package dependencies being pulled into solution setups where a data poco implementing ILibrary is in a data project and doesn't need to pull in the larger staticlibrary package dependencies. -- Review dependencies to see if we can reduce them (can we import abstraction packages instead of full core packages?). -- Expand support to provide a service for exposing files via a temp path or via a temp auth token (media streaming?). Might be too in depth for the purposee of this library though, as such a concept could just wrap and interface with this library via the path provider since each request will check with the path provider if a library path is valid. However, in the current state, temp paths are limited to exposing all files in the directory, thus you'd hav to combine authorization for now to limit file access if so desired. \ No newline at end of file diff --git a/src/Kyse.AspNetCore.StaticLibrary/ILibrary.cs b/src/Kyse.AspNetCore.StaticLibrary.Abstractions/ILibrary.cs similarity index 100% rename from src/Kyse.AspNetCore.StaticLibrary/ILibrary.cs rename to src/Kyse.AspNetCore.StaticLibrary.Abstractions/ILibrary.cs diff --git a/src/Kyse.AspNetCore.StaticLibrary/ILibraryPathProvider.cs b/src/Kyse.AspNetCore.StaticLibrary.Abstractions/ILibraryPathProvider.cs similarity index 100% rename from src/Kyse.AspNetCore.StaticLibrary/ILibraryPathProvider.cs rename to src/Kyse.AspNetCore.StaticLibrary.Abstractions/ILibraryPathProvider.cs diff --git a/src/Kyse.AspNetCore.StaticLibrary.Abstractions/Kyse.AspNetCore.StaticLibrary.Abstractions.csproj b/src/Kyse.AspNetCore.StaticLibrary.Abstractions/Kyse.AspNetCore.StaticLibrary.Abstractions.csproj new file mode 100644 index 0000000..c5a2ee7 --- /dev/null +++ b/src/Kyse.AspNetCore.StaticLibrary.Abstractions/Kyse.AspNetCore.StaticLibrary.Abstractions.csproj @@ -0,0 +1,32 @@ + + + + + + netstandard2.0 + $(CommonVersion) + Jared Fisher + Abstractions for Kyse.AspNetCore.StaticLibrary + Kyse.AspNetCore.StaticLibrary.Abstractions + staticlibrary abstractions + true + + © $(CopyrightYear) Jared Fisher + https://github.com/kyse/Kyse.AspNetCore.StaticLibrary.git + https://github.com/kyse/Kyse.AspNetCore.StaticLibrary + github + Kyse.AspNetCore.StaticLibrary + Kyse.AspNetCore.StaticLibrary + + + + Kyse.AspNetCore.StaticLibrary.Abstractions.xml + + + + + + + + + diff --git a/src/Kyse.AspNetCore.StaticLibrary.Abstractions/Kyse.AspNetCore.StaticLibrary.Abstractions.xml b/src/Kyse.AspNetCore.StaticLibrary.Abstractions/Kyse.AspNetCore.StaticLibrary.Abstractions.xml new file mode 100644 index 0000000..e08b320 --- /dev/null +++ b/src/Kyse.AspNetCore.StaticLibrary.Abstractions/Kyse.AspNetCore.StaticLibrary.Abstractions.xml @@ -0,0 +1,34 @@ + + + + Kyse.AspNetCore.StaticLibrary.Abstractions + + + + + Interface for class providing library info + + + + + The library name used for the sub path route. + + + + + The path local host path to expose with this library. + + + + + The interface for the class providing the ILibrary list. + + + + + Returns the the list of libraries exposed by this static library server. + + + + + diff --git a/src/Kyse.AspNetCore.StaticLibrary/Constants.cs b/src/Kyse.AspNetCore.StaticLibrary/Constants.cs index 0a808eb..d1ceb04 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/Constants.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/Constants.cs @@ -5,7 +5,6 @@ // Changes: // - Including internal classes required for modified files. -using System; using System.Threading.Tasks; namespace Kyse.AspNetCore.StaticLibrary diff --git a/src/Kyse.AspNetCore.StaticLibrary/Helpers.cs b/src/Kyse.AspNetCore.StaticLibrary/Helpers.cs index 20eb5a3..3edecb8 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/Helpers.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/Helpers.cs @@ -14,7 +14,6 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Authorization.Policy; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; diff --git a/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.csproj b/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.csproj index 1a0e50e..44c62a0 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.csproj +++ b/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.csproj @@ -1,20 +1,18 @@ - - 2017 - $([System.DateTime]::Now.ToString(`yyyy`)) - $(CopyrightInitialYear)-$([System.DateTime]::Now.ToString(`yyyy`)) - + - netcoreapp2.0 - 1.0.0 + netstandard2.0 + $(CommonVersion) Jared Fisher Dynamic Library to filesystem mapping with Authorization implementation of Microsoft.AspNetCore.StaticFiles. Kyse.AspNetCore.StaticLibrary staticlibrary staticfiles staticbrowser static files browser auhentication authorization true - AspNetCore 2.0 version. + Moved ILibrary and ILibraryPathProvider to an abstractions package. +Converted to a .NET Standard 2.0 class library. +Optimized references. © $(CopyrightYear) Jared Fisher https://github.com/kyse/Kyse.AspNetCore.StaticLibrary.git https://github.com/kyse/Kyse.AspNetCore.StaticLibrary @@ -22,7 +20,6 @@ - latest Kyse.AspNetCore.StaticLibrary.xml @@ -33,12 +30,15 @@ - - + + + + + True diff --git a/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.xml b/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.xml index c781119..b02cd9a 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.xml +++ b/src/Kyse.AspNetCore.StaticLibrary/Kyse.AspNetCore.StaticLibrary.xml @@ -4,32 +4,6 @@ Kyse.AspNetCore.StaticLibrary - - - Interface for class providing library info - - - - - The library name used for the sub path route. - - - - - The path local host path to expose with this library. - - - - - The interface for the class providing the ILibrary list. - - - - - Returns the the list of libraries exposed by this static library server. - - - Extension methods for the DirectoryBrowserMiddleware diff --git a/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserMiddleware.cs b/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserMiddleware.cs index e438ae3..1c30307 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserMiddleware.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserMiddleware.cs @@ -3,6 +3,7 @@ // - Updated to support class name changes. // - Added authentication and authorization. // - Added dynamic library path mapping. +// - Converted Invoke to async // // Original Copywrite/License Notice: // @@ -10,7 +11,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Linq; using System.Text.Encodings.Web; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; @@ -87,24 +87,28 @@ public LibraryBrowserMiddleware(RequestDelegate next, IHostingEnvironment hostin /// /// /// - public Task Invoke(HttpContext context) + public async Task Invoke(HttpContext context) { // Check if the URL matches any expected paths if (!Helpers.IsGetOrHeadMethod(context.Request.Method) || !Helpers.TryMatchPath(context, _prefixUrl, forDirectory: true, subpath: out PathString libraryPath) || - !Helpers.TryMatchLibrary(libraryPath, _pathProvider.GetLibraries(), forDirectory: true, subpath: out PathString subpath, library: out ILibrary library)) - return _next(context); + !Helpers.TryMatchLibrary(libraryPath, _pathProvider.GetLibraries(), forDirectory: true, + subpath: out PathString subpath, library: out ILibrary library)) + { + await _next(context); + return; + } if (!context.IsAuthenticated(_options)) { context.Response.StatusCode = 401; - return Constants.CompletedTask; + return; } if (!context.IsAuthorized(_options, library, LibraryServerAuthorizationPolicy.Browser)) { context.Response.StatusCode = 403; - return Constants.CompletedTask; + return; } // If the path matches a directory but does not end in a slash, redirect to add the slash. @@ -114,14 +118,16 @@ public Task Invoke(HttpContext context) context.Response.StatusCode = 301; context.Response.Headers[HeaderNames.Location] = context.Request.PathBase + context.Request.Path + "/" + context.Request.QueryString; - return Constants.CompletedTask; + return; } if (TryGetDirectoryInfo(library, subpath, out IDirectoryContents contents)) - return _formatter.GenerateContentAsync(context, contents); + { + await _formatter.GenerateContentAsync(context, contents); + return; + } context.Response.StatusCode = 500; - return Constants.CompletedTask; } private bool TryGetDirectoryInfo(ILibrary library, PathString subpath, out IDirectoryContents contents) diff --git a/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserOptions.cs b/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserOptions.cs index 16681e9..56b31d3 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserOptions.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LibraryBrowserOptions.cs @@ -7,8 +7,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Collections.Generic; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.StaticFiles; namespace Kyse.AspNetCore.StaticLibrary diff --git a/src/Kyse.AspNetCore.StaticLibrary/LibraryFileContext.cs b/src/Kyse.AspNetCore.StaticLibrary/LibraryFileContext.cs index 9b44b3e..09d9454 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LibraryFileContext.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LibraryFileContext.cs @@ -10,15 +10,12 @@ using System; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Headers; -using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; diff --git a/src/Kyse.AspNetCore.StaticLibrary/LibraryFileExtensions.cs b/src/Kyse.AspNetCore.StaticLibrary/LibraryFileExtensions.cs index 45065ac..237d9cb 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LibraryFileExtensions.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LibraryFileExtensions.cs @@ -10,7 +10,6 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Options; namespace Kyse.AspNetCore.StaticLibrary diff --git a/src/Kyse.AspNetCore.StaticLibrary/LibraryFileMiddleware.cs b/src/Kyse.AspNetCore.StaticLibrary/LibraryFileMiddleware.cs index efcdb03..149f7d6 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LibraryFileMiddleware.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LibraryFileMiddleware.cs @@ -1,6 +1,7 @@ // Modified by: Jared Fisher (kyse@kyse.us) // Changes: // - Updated to support class name changes. +// - Converted Invoke to async // // Original Copywrite/License Notice: // @@ -10,14 +11,11 @@ using System; using System.Diagnostics; using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.StaticFiles; -using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using System.Runtime.InteropServices; namespace Kyse.AspNetCore.StaticLibrary { @@ -66,7 +64,7 @@ public LibraryFileMiddleware(RequestDelegate next, IHostingEnvironment hostingEn /// /// /// - public Task Invoke(HttpContext context) + public async Task Invoke(HttpContext context) { var fileContext = new LibraryFileContext(context, _options, _prefixUrl, _logger, _contentTypeProvider, _pathProvider); @@ -91,12 +89,14 @@ public Task Invoke(HttpContext context) if (!context.IsAuthenticated(_options)) { _logger.LogNotAuthenticated(fileContext.Library.Name, fileContext.SubPath, context.Connection?.RemoteIpAddress?.ToString()); - return fileContext.SendStatusAsync(Constants.Status401NotAuthenticated); + await fileContext.SendStatusAsync(Constants.Status401NotAuthenticated); + return; } if (!context.IsAuthorized(_options, fileContext.Library, LibraryServerAuthorizationPolicy.File)) { _logger.LogNotAuthorized(fileContext.Library.Name, fileContext.SubPath, context.User?.Identity?.Name); - return fileContext.SendStatusAsync(Constants.Status403NotAuthorized); + await fileContext.SendStatusAsync(Constants.Status403NotAuthorized); + return; } // If we get here, we can try to serve the file @@ -107,20 +107,25 @@ public Task Invoke(HttpContext context) case LibraryFileContext.PreconditionState.ShouldProcess: if (fileContext.IsHeadMethod) { - return fileContext.SendStatusAsync(Constants.Status200Ok); + await fileContext.SendStatusAsync(Constants.Status200Ok); + return; } if (fileContext.IsRangeRequest) { - return fileContext.SendRangeAsync(); + await fileContext.SendRangeAsync(); + return; } _logger.LogFileServed(fileContext.SubPath, fileContext.PhysicalPath, context.User?.Identity?.Name); - return fileContext.SendAsync(); + await fileContext.SendAsync(); + return; case LibraryFileContext.PreconditionState.NotModified: _logger.LogPathNotModified(fileContext.SubPath); - return fileContext.SendStatusAsync(Constants.Status304NotModified); + await fileContext.SendStatusAsync(Constants.Status304NotModified); + return; case LibraryFileContext.PreconditionState.PreconditionFailed: _logger.LogPreconditionFailed(fileContext.SubPath); - return fileContext.SendStatusAsync(Constants.Status412PreconditionFailed); + await fileContext.SendStatusAsync(Constants.Status412PreconditionFailed); + return; default: var exception = new NotImplementedException(fileContext.GetPreconditionState().ToString()); Debug.Fail(exception.ToString()); @@ -128,7 +133,7 @@ public Task Invoke(HttpContext context) } } - return _next(context); + await _next(context); } } } \ No newline at end of file diff --git a/src/Kyse.AspNetCore.StaticLibrary/LibraryServerExtensions.cs b/src/Kyse.AspNetCore.StaticLibrary/LibraryServerExtensions.cs index bec5cdf..31d5c14 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LibraryServerExtensions.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LibraryServerExtensions.cs @@ -9,7 +9,6 @@ using System; using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting.Internal; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; diff --git a/src/Kyse.AspNetCore.StaticLibrary/LibraryServerOptions.cs b/src/Kyse.AspNetCore.StaticLibrary/LibraryServerOptions.cs index b717034..590faf0 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LibraryServerOptions.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LibraryServerOptions.cs @@ -7,8 +7,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNetCore.StaticFiles.Infrastructure; - namespace Kyse.AspNetCore.StaticLibrary { /// diff --git a/src/Kyse.AspNetCore.StaticLibrary/LoggerExtensions.cs b/src/Kyse.AspNetCore.StaticLibrary/LoggerExtensions.cs index 2b77127..8f66428 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/LoggerExtensions.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/LoggerExtensions.cs @@ -1,6 +1,7 @@ // Modified by: Jared Fisher (kyse@kyse.us) // Changes: // - Updated to support class name changes. +// - Changed some log levels to reduce debug spam. // // Original Copywrite/License Notice: // diff --git a/src/Kyse.AspNetCore.StaticLibrary/SharedOptions.cs b/src/Kyse.AspNetCore.StaticLibrary/SharedOptions.cs index 733c44c..4292518 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/SharedOptions.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/SharedOptions.cs @@ -9,7 +9,6 @@ using System; using System.Collections.Generic; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; namespace Kyse.AspNetCore.StaticLibrary diff --git a/src/Kyse.AspNetCore.StaticLibrary/SharedOptionsBase.cs b/src/Kyse.AspNetCore.StaticLibrary/SharedOptionsBase.cs index 2183c3d..d1a7e07 100644 --- a/src/Kyse.AspNetCore.StaticLibrary/SharedOptionsBase.cs +++ b/src/Kyse.AspNetCore.StaticLibrary/SharedOptionsBase.cs @@ -9,9 +9,7 @@ using System; using System.Collections.Generic; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.FileProviders; namespace Kyse.AspNetCore.StaticLibrary { diff --git a/src/common.props b/src/common.props new file mode 100644 index 0000000..f83ff1f --- /dev/null +++ b/src/common.props @@ -0,0 +1,10 @@ + + + 1.0.1 + + + 2017 + $([System.DateTime]::Now.ToString(`yyyy`)) + $(CopyrightInitialYear)-$([System.DateTime]::Now.ToString(`yyyy`)) + + \ No newline at end of file