From 2ce0fcb26417d3b6ea8708b514f098ce3ed44634 Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Thu, 13 Oct 2022 12:17:13 -0500 Subject: [PATCH] proxy server improvements (#996) --- CHANGELOG.md | 2 + .../Health/Checks/FileNotFoundHealthCheck.cs | 2 +- .../Health/Checks/UnavailableHealthCheck.cs | 2 +- ErsatzTV/Controllers/IptvController.cs | 8 +-- ErsatzTV/Extensions/StringExtensions.cs | 2 +- ErsatzTV/Pages/Artist.razor | 10 ++-- ErsatzTV/Pages/ArtistList.razor | 8 +-- ErsatzTV/Pages/Channels.razor | 4 +- ErsatzTV/Pages/CollectionEditor.razor | 2 +- ErsatzTV/Pages/CollectionItems.razor | 12 ++--- ErsatzTV/Pages/Collections.razor | 8 +-- ErsatzTV/Pages/EpisodeList.razor | 8 +-- ErsatzTV/Pages/FFmpeg.razor | 8 ++- ErsatzTV/Pages/FillerPresetEditor.razor | 2 +- ErsatzTV/Pages/FillerPresets.razor | 4 +- ErsatzTV/Pages/Libraries.razor | 2 +- ErsatzTV/Pages/LocalLibraries.razor | 4 +- ErsatzTV/Pages/LocalLibraryEditor.razor | 4 +- ErsatzTV/Pages/LocalLibraryPathEditor.razor | 2 +- ErsatzTV/Pages/Movie.razor | 6 +-- ErsatzTV/Pages/MovieList.razor | 8 +-- ErsatzTV/Pages/MultiCollectionEditor.razor | 2 +- ErsatzTV/Pages/MusicVideoList.razor | 6 +-- ErsatzTV/Pages/OtherVideoList.razor | 6 +-- ErsatzTV/Pages/Playouts.razor | 2 +- ErsatzTV/Pages/PlexMediaSources.razor | 4 +- ErsatzTV/Pages/Schedules.razor | 6 +-- ErsatzTV/Pages/Search.razor | 26 +++++----- ErsatzTV/Pages/SongList.razor | 6 +-- ErsatzTV/Pages/TelevisionEpisodeList.razor | 12 ++--- ErsatzTV/Pages/TelevisionSeasonList.razor | 10 ++-- .../Pages/TelevisionSeasonSearchResults.razor | 8 +-- ErsatzTV/Pages/TelevisionShowList.razor | 8 +-- ErsatzTV/Pages/TraktLists.razor | 2 +- ErsatzTV/Pages/Trash.razor | 26 +++++----- ErsatzTV/Pages/Watermarks.razor | 4 +- ErsatzTV/Pages/_Host.cshtml | 2 +- ErsatzTV/Shared/MainLayout.razor | 50 +++++++++---------- ErsatzTV/Shared/MediaCard.razor | 2 +- ErsatzTV/Shared/RemoteMediaSourceEditor.razor | 2 +- .../RemoteMediaSourceLibrariesEditor.razor | 2 +- ...oteMediaSourcePathReplacementsEditor.razor | 2 +- ErsatzTV/Shared/RemoteMediaSources.razor | 8 +-- ErsatzTV/Startup.cs | 10 ++++ 44 files changed, 162 insertions(+), 152 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e782974f6..591702233 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Fix bug where tail or fallback filler would sometimes schedule much longer than expected - This only happened with fixed start schedule items following a schedule item with tail or fallback filler - Fix NFO reader bug that caused inaccurate warning messages about invalid XML and incomplete metadata +- Fix reverse proxy SSL termination support by supporting `X-Forwarded-Proto` header ### Added - Add music video credits template system @@ -37,6 +38,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - All groups of part numbers (i.e. all part 1s, all part 2s) will be shuffled - The playout order will then schedule a random part 1 followed by a random part 2, etc - Un-split (`nil`) episodes will be randomly placed between re-combined parts (e.g. part1, part2, part3, un-split, part1, part2, part3) +- Add `ETV_BASE_URL` environment variable to support reverse proxies that use paths (e.g. `/ersatztv`) ### Changed - No longer place watermarks within content by default (e.g. within 4:3 content padded to a 16:9 resolution) diff --git a/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs b/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs index 2790b7c40..d17856142 100644 --- a/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs +++ b/ErsatzTV.Infrastructure/Health/Checks/FileNotFoundHealthCheck.cs @@ -58,7 +58,7 @@ public class FileNotFoundHealthCheck : BaseHealthCheck, IFileNotFoundHealthCheck return WarningResult( $"There are {count} items that do not exist on disk, including the following: {files}", - "/media/trash"); + "media/trash"); } return OkResult(); diff --git a/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs b/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs index f21f6f976..5d5d24f68 100644 --- a/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs +++ b/ErsatzTV.Infrastructure/Health/Checks/UnavailableHealthCheck.cs @@ -83,7 +83,7 @@ public class UnavailableHealthCheck : BaseHealthCheck, IUnavailableHealthCheck return WarningResult( $"There are {count} items that are unavailable because ErsatzTV cannot find them on disk, including the following: {files}", - "/search?query=state%3aUnavailable"); + "search?query=state%3aUnavailable"); } return OkResult(); diff --git a/ErsatzTV/Controllers/IptvController.cs b/ErsatzTV/Controllers/IptvController.cs index 91ff7846b..c61356ec9 100644 --- a/ErsatzTV/Controllers/IptvController.cs +++ b/ErsatzTV/Controllers/IptvController.cs @@ -77,7 +77,7 @@ public class IptvController : ControllerBase mode = "ts"; break; default: - return Redirect($"/iptv/channel/{channelNumber}.m3u8"); + return Redirect($"~/iptv/channel/{channelNumber}.m3u8"); } } } @@ -167,7 +167,7 @@ public class IptvController : ControllerBase mode = "segmenter"; break; default: - return Redirect($"/iptv/channel/{channelNumber}.ts"); + return Redirect($"~/iptv/channel/{channelNumber}.ts"); } } } @@ -184,7 +184,7 @@ public class IptvController : ControllerBase "Session started; returning multi-variant playlist for channel {Channel}", channelNumber); return Content(GetMultiVariantPlaylist(channelNumber), "application/x-mpegurl"); - // return Redirect($"/iptv/session/{channelNumber}/hls.m3u8"); + // return Redirect($"~/iptv/session/{channelNumber}/hls.m3u8"); }, error => { @@ -195,7 +195,7 @@ public class IptvController : ControllerBase "Session is already active; returning multi-variant playlist for channel {Channel}", channelNumber); return Content(GetMultiVariantPlaylist(channelNumber), "application/x-mpegurl"); - // return RedirectPreserveMethod($"/iptv/session/{channelNumber}/hls.m3u8"); + // return RedirectPreserveMethod($"iptv/session/{channelNumber}/hls.m3u8"); default: _logger.LogWarning( "Failed to start segmenter for channel {ChannelNumber}: {Error}", diff --git a/ErsatzTV/Extensions/StringExtensions.cs b/ErsatzTV/Extensions/StringExtensions.cs index 343d797d1..921bd4543 100644 --- a/ErsatzTV/Extensions/StringExtensions.cs +++ b/ErsatzTV/Extensions/StringExtensions.cs @@ -33,7 +33,7 @@ public static class StringExtensions public static string GetRelativeSearchQuery(this string query) { (string key, string value) = EncodeQuery(query); - return $"/search?{key}={value}"; + return $"search?{key}={value}"; } private static string DecodeBase64(this StringValues input) => diff --git a/ErsatzTV/Pages/Artist.razor b/ErsatzTV/Pages/Artist.razor index 0a2527a55..36623ab1c 100644 --- a/ErsatzTV/Pages/Artist.razor +++ b/ErsatzTV/Pages/Artist.razor @@ -16,7 +16,7 @@
@if (!string.IsNullOrWhiteSpace(_artist.FanArt)) { - fan art + fan art } @@ -25,7 +25,7 @@ { artist thumbnail + src="@($"artwork/thumbnails/{_artist.Thumbnail}")" alt="artist thumbnail"/> }
@_artist.Name @@ -125,7 +125,7 @@ @if (!string.IsNullOrWhiteSpace(musicVideo.Poster)) { - + @if (musicVideo.State == MediaItemState.FileNotFound) {
@@ -245,7 +245,7 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { await _mediator.Send(new AddArtistToCollection(collection.Id, ArtistId), _cts.Token); - _navigationManager.NavigateTo($"/media/collections/{collection.Id}"); + _navigationManager.NavigateTo($"media/collections/{collection.Id}"); } } @@ -259,7 +259,7 @@ if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule) { await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.Artist, null, null, null, ArtistId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token); - _navigationManager.NavigateTo($"/schedules/{schedule.Id}/items"); + _navigationManager.NavigateTo($"schedules/{schedule.Id}/items"); } } diff --git a/ErsatzTV/Pages/ArtistList.razor b/ErsatzTV/Pages/ArtistList.razor index b12255d8b..2ddc0ac3f 100644 --- a/ErsatzTV/Pages/ArtistList.razor +++ b/ErsatzTV/Pages/ArtistList.razor @@ -55,7 +55,7 @@ } @@ -99,7 +99,7 @@ private void PrevPage() { - string uri = $"/media/music/artists/page/{PageNumber - 1}"; + string uri = $"media/music/artists/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -110,7 +110,7 @@ private void NextPage() { - string uri = $"/media/music/artists/page/{PageNumber + 1}"; + string uri = $"media/music/artists/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/Channels.razor b/ErsatzTV/Pages/Channels.razor index 73e30e134..890887fa4 100644 --- a/ErsatzTV/Pages/Channels.razor +++ b/ErsatzTV/Pages/Channels.razor @@ -58,7 +58,7 @@
+ Link="@($"channels/{context.Id}")"> @@ -73,7 +73,7 @@ - + Add Channel diff --git a/ErsatzTV/Pages/CollectionEditor.razor b/ErsatzTV/Pages/CollectionEditor.razor index f03c99e6b..179168d64 100644 --- a/ErsatzTV/Pages/CollectionEditor.razor +++ b/ErsatzTV/Pages/CollectionEditor.razor @@ -83,7 +83,7 @@ _snackbar.Add(error.Value, Severity.Error); _logger.LogError("Error saving collection: {Error}", error.Value); }, - () => _navigationManager.NavigateTo(_model.Id > 0 ? $"/media/collections/{_model.Id}" : "/media/collections")); + () => _navigationManager.NavigateTo(_model.Id > 0 ? $"media/collections/{_model.Id}" : "media/collections")); } } diff --git a/ErsatzTV/Pages/CollectionItems.razor b/ErsatzTV/Pages/CollectionItems.razor index 72d9b6020..b4286819d 100644 --- a/ErsatzTV/Pages/CollectionItems.razor +++ b/ErsatzTV/Pages/CollectionItems.razor @@ -32,7 +32,7 @@
@_data.Name + Link="@($"media/collections/{Id}/edit")"/>
@if (_data.MovieCards.Any()) { @@ -95,7 +95,7 @@ @foreach (MovieCardViewModel card in OrderMovies(_data.MovieCards)) { m.SortTitle)) { m.SortTitle)) { e.Aired)) { e.SortTitle)) {
- + Add Collection - + Add Multi Collection
@@ -38,7 +38,7 @@
+ Link="@($"media/collections/{context.Id}")"> @@ -76,7 +76,7 @@
+ Link="@($"media/multi-collections/{context.Id}/edit")"> diff --git a/ErsatzTV/Pages/EpisodeList.razor b/ErsatzTV/Pages/EpisodeList.razor index 1f543d561..b07439a1e 100644 --- a/ErsatzTV/Pages/EpisodeList.razor +++ b/ErsatzTV/Pages/EpisodeList.razor @@ -55,7 +55,7 @@ } @@ -99,7 +99,7 @@ private void PrevPage() { - string uri = $"/media/tv/episodes/page/{PageNumber - 1}"; + string uri = $"media/tv/episodes/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -110,7 +110,7 @@ private void NextPage() { - string uri = $"/media/tv/episodes/page/{PageNumber + 1}"; + string uri = $"media/tv/episodes/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/FFmpeg.razor b/ErsatzTV/Pages/FFmpeg.razor index fc763000a..c1c9d0097 100644 --- a/ErsatzTV/Pages/FFmpeg.razor +++ b/ErsatzTV/Pages/FFmpeg.razor @@ -3,8 +3,6 @@ @implements IDisposable @inject IDialogService _dialog @inject IMediator _mediator -@inject ILogger _logger -@inject ISnackbar _snackbar @inject NavigationManager _navigationManager @@ -44,7 +42,7 @@
+ Link="@($"ffmpeg/{context.Id}")"> @@ -61,7 +59,7 @@ - + Add Profile @@ -105,7 +103,7 @@ DialogResult dialogResult = await dialog.Result; if (!dialogResult.Cancelled && dialogResult.Data is FFmpegProfileViewModel data) { - _navigationManager.NavigateTo($"/ffmpeg/{data.Id}"); + _navigationManager.NavigateTo($"ffmpeg/{data.Id}"); } } diff --git a/ErsatzTV/Pages/FillerPresetEditor.razor b/ErsatzTV/Pages/FillerPresetEditor.razor index 32f9cd134..d6628f3f0 100644 --- a/ErsatzTV/Pages/FillerPresetEditor.razor +++ b/ErsatzTV/Pages/FillerPresetEditor.razor @@ -230,7 +230,7 @@ _snackbar.Add(error.Value, Severity.Error); _logger.LogError("Error saving filler preset: {Error}", error.Value); }, - () => _navigationManager.NavigateTo("/media/filler/presets")); + () => _navigationManager.NavigateTo("media/filler/presets")); } } diff --git a/ErsatzTV/Pages/FillerPresets.razor b/ErsatzTV/Pages/FillerPresets.razor index fa9bf45d2..b37cf4446 100644 --- a/ErsatzTV/Pages/FillerPresets.razor +++ b/ErsatzTV/Pages/FillerPresets.razor @@ -8,7 +8,7 @@
- + Add Filler Preset
@@ -49,7 +49,7 @@
+ Link="@($"media/filler/presets/{context.Id}/edit")"> diff --git a/ErsatzTV/Pages/Libraries.razor b/ErsatzTV/Pages/Libraries.razor index d56049ef2..7e8608df1 100644 --- a/ErsatzTV/Pages/Libraries.razor +++ b/ErsatzTV/Pages/Libraries.razor @@ -77,7 +77,7 @@ } + Link="@($"search?query=library_id%3a{context.Id}")">
diff --git a/ErsatzTV/Pages/LocalLibraries.razor b/ErsatzTV/Pages/LocalLibraries.razor index 64238ecd7..9d2e9670b 100644 --- a/ErsatzTV/Pages/LocalLibraries.razor +++ b/ErsatzTV/Pages/LocalLibraries.razor @@ -32,7 +32,7 @@ + Link="@($"media/sources/local/{context.Id}/edit")"> @@ -45,7 +45,7 @@ - + Add Local Library
diff --git a/ErsatzTV/Pages/LocalLibraryEditor.razor b/ErsatzTV/Pages/LocalLibraryEditor.razor index 97a877082..bfda00132 100644 --- a/ErsatzTV/Pages/LocalLibraryEditor.razor +++ b/ErsatzTV/Pages/LocalLibraryEditor.razor @@ -148,7 +148,7 @@ var request = new MoveLocalLibraryPath(libraryPath.Id, library.Id); Either moveResult = await _mediator.Send(request, _cts.Token); moveResult.Match( - _ => _navigationManager.NavigateTo($"/media/sources/local/{library.Id}/edit"), + _ => _navigationManager.NavigateTo($"media/sources/local/{library.Id}/edit"), error => { _snackbar.Add(error.Value, Severity.Error); @@ -214,7 +214,7 @@ _model.Paths.Map(p => p.Path).ToList()), _cts.Token); result.Match( - _ => _navigationManager.NavigateTo("/media/sources/local"), + _ => _navigationManager.NavigateTo("media/sources/local"), error => { _snackbar.Add(error.Value, Severity.Error); diff --git a/ErsatzTV/Pages/LocalLibraryPathEditor.razor b/ErsatzTV/Pages/LocalLibraryPathEditor.razor index b0ec99e03..fe12a5cd0 100644 --- a/ErsatzTV/Pages/LocalLibraryPathEditor.razor +++ b/ErsatzTV/Pages/LocalLibraryPathEditor.razor @@ -81,7 +81,7 @@ if (_locker.LockLibrary(_library.Id)) { await _channel.WriteAsync(new ScanLocalLibraryIfNeeded(_library.Id), _cts.Token); - _navigationManager.NavigateTo("/media/libraries"); + _navigationManager.NavigateTo("media/libraries"); } }); } diff --git a/ErsatzTV/Pages/Movie.razor b/ErsatzTV/Pages/Movie.razor index 4f2311a73..d3dda6e5b 100644 --- a/ErsatzTV/Pages/Movie.razor +++ b/ErsatzTV/Pages/Movie.razor @@ -19,7 +19,7 @@ } else { - fan art + fan art } } @@ -38,7 +38,7 @@ { movie poster + src="@($"artwork/posters/{_movie.Poster}")" alt="movie poster"/> } @if (_movie.MediaItemState == MediaItemState.FileNotFound) { @@ -249,7 +249,7 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { await _mediator.Send(new AddMovieToCollection(collection.Id, MovieId), _cts.Token); - _navigationManager.NavigateTo($"/media/collections/{collection.Id}"); + _navigationManager.NavigateTo($"media/collections/{collection.Id}"); } } diff --git a/ErsatzTV/Pages/MovieList.razor b/ErsatzTV/Pages/MovieList.razor index b66da6069..d12255fee 100644 --- a/ErsatzTV/Pages/MovieList.razor +++ b/ErsatzTV/Pages/MovieList.razor @@ -55,7 +55,7 @@ } @@ -98,7 +98,7 @@ private void PrevPage() { - string uri = $"/media/movies/page/{PageNumber - 1}"; + string uri = $"media/movies/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -109,7 +109,7 @@ private void NextPage() { - string uri = $"/media/movies/page/{PageNumber + 1}"; + string uri = $"media/movies/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/MultiCollectionEditor.razor b/ErsatzTV/Pages/MultiCollectionEditor.razor index acdc1ea88..c004651ac 100644 --- a/ErsatzTV/Pages/MultiCollectionEditor.razor +++ b/ErsatzTV/Pages/MultiCollectionEditor.razor @@ -186,7 +186,7 @@ _snackbar.Add(error.Value, Severity.Error); _logger.LogError("Error saving collection: {Error}", error.Value); }, - () => _navigationManager.NavigateTo("/media/collections")); + () => _navigationManager.NavigateTo("media/collections")); } } diff --git a/ErsatzTV/Pages/MusicVideoList.razor b/ErsatzTV/Pages/MusicVideoList.razor index 9e554e75a..0da5482ad 100644 --- a/ErsatzTV/Pages/MusicVideoList.razor +++ b/ErsatzTV/Pages/MusicVideoList.razor @@ -67,7 +67,7 @@ @if (_data.PageMap.IsSome) { } @@ -99,7 +99,7 @@ private void PrevPage() { - string uri = $"/media/music/videos/page/{PageNumber - 1}"; + string uri = $"media/music/videos/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -110,7 +110,7 @@ private void NextPage() { - string uri = $"/media/music/videos/page/{PageNumber + 1}"; + string uri = $"media/music/videos/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/OtherVideoList.razor b/ErsatzTV/Pages/OtherVideoList.razor index 5439447e1..d0b60d925 100644 --- a/ErsatzTV/Pages/OtherVideoList.razor +++ b/ErsatzTV/Pages/OtherVideoList.razor @@ -67,7 +67,7 @@ @if (_data.PageMap.IsSome) { } @@ -99,7 +99,7 @@ private void PrevPage() { - string uri = $"/media/other/videos/page/{PageNumber - 1}"; + string uri = $"media/other/videos/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -110,7 +110,7 @@ private void NextPage() { - string uri = $"/media/other/videos/page/{PageNumber + 1}"; + string uri = $"media/other/videos/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/Playouts.razor b/ErsatzTV/Pages/Playouts.razor index 15c74e47f..5d063a292 100644 --- a/ErsatzTV/Pages/Playouts.razor +++ b/ErsatzTV/Pages/Playouts.razor @@ -7,7 +7,7 @@ @inject IMediator _mediator - + Add Playout + Link="@($"media/sources/plex/{context.Id}/libraries")"> + Link="@($"media/sources/plex/{context.Id}/paths")">
diff --git a/ErsatzTV/Pages/Schedules.razor b/ErsatzTV/Pages/Schedules.razor index 82c637ea3..c0793a40a 100644 --- a/ErsatzTV/Pages/Schedules.razor +++ b/ErsatzTV/Pages/Schedules.razor @@ -34,12 +34,12 @@
+ Link="@($"schedules/{context.Id}")"> + Link="@($"schedules/{context.Id}/items")"> @@ -54,7 +54,7 @@ - + Add Schedule diff --git a/ErsatzTV/Pages/Search.razor b/ErsatzTV/Pages/Search.razor index cd53c273c..0d04097ab 100644 --- a/ErsatzTV/Pages/Search.razor +++ b/ErsatzTV/Pages/Search.razor @@ -110,7 +110,7 @@ @foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle)) { s.SortTitle)) { s.SortTitle)) { s.SortTitle)) { } @@ -99,7 +99,7 @@ private void PrevPage() { - string uri = $"/media/music/songs/page/{PageNumber - 1}"; + string uri = $"media/music/songs/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -110,7 +110,7 @@ private void NextPage() { - string uri = $"/media/music/songs/page/{PageNumber + 1}"; + string uri = $"media/music/songs/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/TelevisionEpisodeList.razor b/ErsatzTV/Pages/TelevisionEpisodeList.razor index 6b48a3657..04676f27c 100644 --- a/ErsatzTV/Pages/TelevisionEpisodeList.razor +++ b/ErsatzTV/Pages/TelevisionEpisodeList.razor @@ -23,7 +23,7 @@ } else { - fan art + fan art } } @@ -41,11 +41,11 @@ { season poster + src="@($"artwork/posters/{_season.Poster}")" alt="season poster"/> } }
- + @_season.Title @_season.Name @@ -81,7 +81,7 @@ } else { - + } @if (episode.State == MediaItemState.FileNotFound) { @@ -219,7 +219,7 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { await _mediator.Send(new AddSeasonToCollection(collection.Id, SeasonId), _cts.Token); - _navigationManager.NavigateTo($"/media/collections/{collection.Id}"); + _navigationManager.NavigateTo($"media/collections/{collection.Id}"); } } @@ -234,7 +234,7 @@ if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule) { await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionSeason, null, null, null, SeasonId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token); - _navigationManager.NavigateTo($"/schedules/{schedule.Id}/items"); + _navigationManager.NavigateTo($"schedules/{schedule.Id}/items"); } } diff --git a/ErsatzTV/Pages/TelevisionSeasonList.razor b/ErsatzTV/Pages/TelevisionSeasonList.razor index a5e2cd407..f30909d05 100644 --- a/ErsatzTV/Pages/TelevisionSeasonList.razor +++ b/ErsatzTV/Pages/TelevisionSeasonList.razor @@ -23,7 +23,7 @@ } else { - fan art + fan art } } @@ -41,7 +41,7 @@ { movie poster + src="@($"artwork/posters/{_show.Poster}")" alt="movie poster"/> } }
@@ -144,7 +144,7 @@ @foreach (TelevisionSeasonCardViewModel card in _data.Cards) { } @@ -215,7 +215,7 @@ if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { await _mediator.Send(new AddShowToCollection(collection.Id, ShowId), _cts.Token); - _navigationManager.NavigateTo($"/media/collections/{collection.Id}"); + _navigationManager.NavigateTo($"media/collections/{collection.Id}"); } } @@ -229,7 +229,7 @@ if (!result.Cancelled && result.Data is ProgramScheduleViewModel schedule) { await _mediator.Send(new AddProgramScheduleItem(schedule.Id, StartType.Dynamic, null, PlayoutMode.One, ProgramScheduleItemCollectionType.TelevisionShow, null, null, null, ShowId, PlaybackOrder.Shuffle, null, null, TailMode.None, null, GuideMode.Normal, null, null, null, null, null, null, null, null, null, null), _cts.Token); - _navigationManager.NavigateTo($"/schedules/{schedule.Id}/items"); + _navigationManager.NavigateTo($"schedules/{schedule.Id}/items"); } } diff --git a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor index ac7dd08f8..69dea28c7 100644 --- a/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor +++ b/ErsatzTV/Pages/TelevisionSeasonSearchResults.razor @@ -55,7 +55,7 @@ } @@ -98,7 +98,7 @@ private void PrevPage() { - string uri = $"/media/tv/seasons/page/{PageNumber - 1}"; + string uri = $"media/tv/seasons/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -109,7 +109,7 @@ private void NextPage() { - string uri = $"/media/tv/seasons/page/{PageNumber + 1}"; + string uri = $"media/tv/seasons/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/TelevisionShowList.razor b/ErsatzTV/Pages/TelevisionShowList.razor index 934a23ea7..ca045c8e6 100644 --- a/ErsatzTV/Pages/TelevisionShowList.razor +++ b/ErsatzTV/Pages/TelevisionShowList.razor @@ -55,7 +55,7 @@ } @@ -98,7 +98,7 @@ private void PrevPage() { - string uri = $"/media/tv/shows/page/{PageNumber - 1}"; + string uri = $"media/tv/shows/page/{PageNumber - 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); @@ -109,7 +109,7 @@ private void NextPage() { - string uri = $"/media/tv/shows/page/{PageNumber + 1}"; + string uri = $"media/tv/shows/page/{PageNumber + 1}"; if (!string.IsNullOrWhiteSpace(_query)) { (string key, string value) = _query.EncodeQuery(); diff --git a/ErsatzTV/Pages/TraktLists.razor b/ErsatzTV/Pages/TraktLists.razor index 70d604deb..1c5984370 100644 --- a/ErsatzTV/Pages/TraktLists.razor +++ b/ErsatzTV/Pages/TraktLists.razor @@ -48,7 +48,7 @@ + Link="@($"search?query=trakt_list%3a{context.TraktId}")"> diff --git a/ErsatzTV/Pages/Trash.razor b/ErsatzTV/Pages/Trash.razor index 70efded27..e464389a0 100644 --- a/ErsatzTV/Pages/Trash.razor +++ b/ErsatzTV/Pages/Trash.razor @@ -107,7 +107,7 @@ @foreach (MovieCardViewModel card in _movies.Cards.OrderBy(m => m.SortTitle)) { s.SortTitle)) { s.SortTitle)) { s.SortTitle)) { + Link="@($"watermarks/{context.Id}")"> @@ -65,7 +65,7 @@ - + Add Watermark diff --git a/ErsatzTV/Pages/_Host.cshtml b/ErsatzTV/Pages/_Host.cshtml index 00f642f25..d61c46c2a 100644 --- a/ErsatzTV/Pages/_Host.cshtml +++ b/ErsatzTV/Pages/_Host.cshtml @@ -29,7 +29,7 @@ $.ajax({ data: data, type: 'POST', - url: `/media/collections/${collectionId}/items` + url: `media/collections/${collectionId}/items` }); } }); diff --git a/ErsatzTV/Shared/MainLayout.razor b/ErsatzTV/Shared/MainLayout.razor index 362e27a22..66f5a16c3 100644 --- a/ErsatzTV/Shared/MainLayout.razor +++ b/ErsatzTV/Shared/MainLayout.razor @@ -13,8 +13,8 @@ @@ -61,8 +61,8 @@ - M3U - XMLTV + M3U + XMLTV @* API *@ @@ -76,33 +76,33 @@ - Channels - FFmpeg Profiles - Watermarks + Channels + FFmpeg Profiles + Watermarks - Local - Emby - Jellyfin - Plex + Local + Emby + Jellyfin + Plex - Libraries - Trash - TV Shows - Movies - Music - Other Videos - Songs + Libraries + Trash + TV Shows + Movies + Music + Other Videos + Songs - Collections - Trakt Lists - Filler Presets + Collections + Trakt Lists + Filler Presets - Schedules - Playouts - Settings - Logs + Schedules + Playouts + Settings + Logs ErsatzTV Version diff --git a/ErsatzTV/Shared/MediaCard.razor b/ErsatzTV/Shared/MediaCard.razor index b1784c9e0..972a764b9 100644 --- a/ErsatzTV/Shared/MediaCard.razor +++ b/ErsatzTV/Shared/MediaCard.razor @@ -153,7 +153,7 @@ return string.IsNullOrWhiteSpace(Data.Poster) ? "position: relative" - : $"position: relative; background-image: url(/artwork/{PathForArtwork()}/{Data.Poster}); background-size: cover; background-position: center"; + : $"position: relative; background-image: url(artwork/{PathForArtwork()}/{Data.Poster}); background-size: cover; background-position: center"; } private string PathForArtwork() => ArtworkKind switch diff --git a/ErsatzTV/Shared/RemoteMediaSourceEditor.razor b/ErsatzTV/Shared/RemoteMediaSourceEditor.razor index 689dda27b..55a56bac1 100644 --- a/ErsatzTV/Shared/RemoteMediaSourceEditor.razor +++ b/ErsatzTV/Shared/RemoteMediaSourceEditor.razor @@ -53,7 +53,7 @@ { Either result = await SaveSecrets(_model); result.Match( - _ => _navigationManager.NavigateTo($"/media/sources/{Name.ToLowerInvariant()}"), + _ => _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"), error => { _snackbar.Add(error.Value, Severity.Error); diff --git a/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor b/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor index e733020c4..a7bcc137c 100644 --- a/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor +++ b/ErsatzTV/Shared/RemoteMediaSourceLibrariesEditor.razor @@ -114,7 +114,7 @@ } } - _navigationManager.NavigateTo($"/media/sources/{Name.ToLowerInvariant()}"); + _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}"); }); } diff --git a/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor b/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor index 67750dbc2..bceca3b2e 100644 --- a/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor +++ b/ErsatzTV/Shared/RemoteMediaSourcePathReplacementsEditor.razor @@ -139,7 +139,7 @@ _snackbar.Add($"Unexpected error saving path replacements: {error.Value}", Severity.Error); _logger.LogError("Unexpected error saving path replacements: {Error}", error.Value); }, - () => _navigationManager.NavigateTo($"/media/sources/{Name.ToLowerInvariant()}")); + () => _navigationManager.NavigateTo($"media/sources/{Name.ToLowerInvariant()}")); } } \ No newline at end of file diff --git a/ErsatzTV/Shared/RemoteMediaSources.razor b/ErsatzTV/Shared/RemoteMediaSources.razor index 0d05e45a1..e5a6502ee 100644 --- a/ErsatzTV/Shared/RemoteMediaSources.razor +++ b/ErsatzTV/Shared/RemoteMediaSources.razor @@ -35,12 +35,12 @@ + Link="@($"media/sources/{Name.ToLowerInvariant()}/{context.Id}/libraries")"> + Link="@($"media/sources/{Name.ToLowerInvariant()}/{context.Id}/paths")">
@@ -60,7 +60,7 @@ { Connect @Name @@ -70,7 +70,7 @@ { Fix @Name Connection diff --git a/ErsatzTV/Startup.cs b/ErsatzTV/Startup.cs index d15a6e3c1..4d97d2c69 100644 --- a/ErsatzTV/Startup.cs +++ b/ErsatzTV/Startup.cs @@ -59,6 +59,7 @@ using FluentValidation.AspNetCore; using Ganss.Xss; using MediatR; using MediatR.Courier.DependencyInjection; +using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.StaticFiles; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.FileProviders; @@ -87,6 +88,7 @@ public class Startup { BugsnagConfiguration bugsnagConfig = Configuration.GetSection("Bugsnag").Get(); services.Configure(Configuration.GetSection("Bugsnag")); + services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.All; }); services.AddBugsnag( configuration => @@ -269,8 +271,16 @@ public class Startup public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + string baseUrl = Environment.GetEnvironmentVariable("ETV_BASE_URL"); + if (!string.IsNullOrWhiteSpace(baseUrl)) + { + app.UsePathBase(baseUrl); + } + app.UseCors("AllowAll"); + app.UseForwardedHeaders(); + // app.UseHttpLogging(); // app.UseSerilogRequestLogging(); app.UseStaticFiles();