From d4a35f1d1d509b4725c5179a32a8c1898a289019 Mon Sep 17 00:00:00 2001 From: marcobaobao Date: Tue, 4 Jun 2024 10:49:55 +0200 Subject: [PATCH] Support for reverse proxy subdir. Closes #110 #150 --- frontend/src/assets/i18n.yaml | 3 ++- frontend/src/atoms/settings.ts | 13 +++++++++- frontend/src/views/Settings.tsx | 44 ++++++++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/frontend/src/assets/i18n.yaml b/frontend/src/assets/i18n.yaml index cdcb7dd..7f0fa03 100644 --- a/frontend/src/assets/i18n.yaml +++ b/frontend/src/assets/i18n.yaml @@ -34,7 +34,8 @@ languages: clipboardAction: Copied URL to clipboard playlistCheckbox: Download playlist (it will take time, after submitting you may close this window) restartAppMessage: Needs a page reload to take effect - servedFromReverseProxyCheckbox: Is behind a reverse proxy subfolder + servedFromReverseProxyCheckbox: Is behind a reverse proxy + urlBase: URL base, for reverse proxy support (subdir), defaults to empty newDownloadButton: New download homeButtonLabel: Home archiveButtonLabel: Archive diff --git a/frontend/src/atoms/settings.ts b/frontend/src/atoms/settings.ts index ea7fb0e..cda89d1 100644 --- a/frontend/src/atoms/settings.ts +++ b/frontend/src/atoms/settings.ts @@ -135,6 +135,15 @@ export const servedFromReverseProxyState = atom({ ] }) +export const servedFromReverseProxySubDirState = atom({ + key: 'servedFromReverseProxyState', + default: localStorage.getItem('reverseProxySubDir') ?? '', + effects: [ + ({ onSet }) => + onSet(a => localStorage.setItem('reverseProxySubDir', a.toString())) + ] +}) + export const appTitleState = atom({ key: 'appTitleState', default: localStorage.getItem('appTitle') ?? 'yt-dlp Web UI', @@ -147,7 +156,9 @@ export const appTitleState = atom({ export const serverAddressAndPortState = selector({ key: 'serverAddressAndPortState', get: ({ get }) => get(servedFromReverseProxyState) - ? `${get(serverAddressState)}` + ? get(servedFromReverseProxySubDirState) ? + `${get(serverAddressState)}/${get(servedFromReverseProxySubDirState)}/` + : `${get(serverAddressState)}` : `${get(serverAddressState)}:${get(serverPortState)}` }) diff --git a/frontend/src/views/Settings.tsx b/frontend/src/views/Settings.tsx index d74b086..89a28c2 100644 --- a/frontend/src/views/Settings.tsx +++ b/frontend/src/views/Settings.tsx @@ -39,6 +39,7 @@ import { latestCliArgumentsState, pathOverridingState, servedFromReverseProxyState, + servedFromReverseProxySubDirState, serverAddressState, serverPortState, themeState @@ -53,6 +54,7 @@ import { validateDomain, validateIP } from '../utils' // NEED ABSOLUTELY TO BE SPLIT IN MULTIPLE COMPONENTS export default function Settings() { const [reverseProxy, setReverseProxy] = useRecoilState(servedFromReverseProxyState) + const [baseURL, setBaseURL] = useRecoilState(servedFromReverseProxySubDirState) const [formatSelection, setFormatSelection] = useRecoilState(formatSelectionState) const [pathOverriding, setPathOverriding] = useRecoilState(pathOverridingState) const [fileRenaming, setFileRenaming] = useRecoilState(fileRenamingState) @@ -73,9 +75,20 @@ export default function Settings() { const argsBuilder = useMemo(() => new CliArguments().fromString(cliArgs), []) + const baseURL$ = useMemo(() => new Subject(), []) const serverAddr$ = useMemo(() => new Subject(), []) const serverPort$ = useMemo(() => new Subject(), []) + useEffect(() => { + const sub = baseURL$ + .pipe(debounceTime(500)) + .subscribe(baseURL => { + setBaseURL(baseURL) + pushMessage(i18n.t('restartAppMessage'), 'info') + }) + return () => sub.unsubscribe() + }, []) + useEffect(() => { const sub = serverAddr$ .pipe( @@ -145,7 +158,7 @@ export default function Settings() { minHeight: 240, }} > - + {i18n.t('settingsAnchor')} @@ -183,6 +196,9 @@ export default function Settings() { /> + + Reverse Proxy + } label={i18n.t('servedFromReverseProxyCheckbox')} + sx={{ mb: 1 }} + /> + { + let value = e.currentTarget.value + if (value.startsWith('/')) { + value = value.substring(1) + } + if (value.endsWith('/')) { + value = value.substring(0, value.length - 1) + } + baseURL$.next(value) + }} sx={{ mb: 2 }} /> + + Appaerance + @@ -227,6 +262,9 @@ export default function Settings() { + + General download settings + } label={i18n.t('noMTimeCheckbox')} - sx={{ mt: 3 }} + /> - + Cookies