diff --git a/CHANGELOG.md b/CHANGELOG.md index 78af7f5c8..a3b81911e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ - Images, videos, and other non-text content is now wider in View Mode - Notes may now be deleted directly from the history page - CodiMD instances can now be branded either with a '@ ' or '@ ' after the CodiMD logo and text +- Images will be loaded via proxy if an image proxy is configured in the backend - Asciinema videos may now be embedded by pasting the URL of one video into a single line ### Changed diff --git a/public/api/v2/config b/public/api/v2/config index 1cd89f77d..ba74eae9c 100644 --- a/public/api/v2/config +++ b/public/api/v2/config @@ -26,6 +26,7 @@ "oauth2": "Olaf2", "saml": "aufSAMLn.de" }, + "useImageProxy": false, "specialLinks": { "privacy": "https://example.com/privacy", "termsOfUse": "https://example.com/termsOfUse", diff --git a/src/api/backend-config/types.ts b/src/api/backend-config/types.ts index 844a4e334..77c299214 100644 --- a/src/api/backend-config/types.ts +++ b/src/api/backend-config/types.ts @@ -4,6 +4,7 @@ export interface BackendConfig { branding: BrandingConfig, banner: BannerConfig, customAuthNames: CustomAuthNames, + useImageProxy: boolean, specialLinks: SpecialLinks, version: BackendVersion, } diff --git a/src/api/imageProxy.ts b/src/api/imageProxy.ts new file mode 100644 index 000000000..c80a27246 --- /dev/null +++ b/src/api/imageProxy.ts @@ -0,0 +1,15 @@ +import { ImageProxyResponse } from '../components/editor/markdown-renderer/replace-components/image/types' +import { expectResponseCode, getBackendUrl } from '../utils/apiUtils' +import { defaultFetchConfig } from './default' + +export const getProxiedUrl = async (imageUrl: string): Promise => { + const response = await fetch(getBackendUrl() + '/media/proxy', { + ...defaultFetchConfig, + method: 'POST', + body: JSON.stringify({ + src: imageUrl + }) + }) + expectResponseCode(response) + return await response.json() as Promise +} diff --git a/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx b/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx index b2d278b14..02d2830ad 100644 --- a/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx +++ b/src/components/editor/markdown-renderer/replace-components/image/image-frame.tsx @@ -1,7 +1,28 @@ -import React from 'react' +import React, { useEffect, useState } from 'react' +import { useSelector } from 'react-redux' +import { getProxiedUrl } from '../../../../../api/imageProxy' +import { ApplicationState } from '../../../../../redux' + +export const ImageFrame: React.FC> = ({ alt, src, ...props }) => { + const [imageUrl, setImageUrl] = useState('') + const imageProxyEnabled = useSelector((state: ApplicationState) => state.backendConfig.useImageProxy) + + useEffect(() => { + if (!imageProxyEnabled || !src) { + return + } + getProxiedUrl(src) + .then(proxyResponse => setImageUrl(proxyResponse.src)) + .catch(err => console.error(err)) + }, [imageProxyEnabled, src]) + + if (imageProxyEnabled) { + return ( + {alt} + ) + } -export const ImageFrame: React.FC> = ({alt, ...props}) => { return ( - {alt} + {alt} ) } diff --git a/src/components/editor/markdown-renderer/replace-components/image/types.ts b/src/components/editor/markdown-renderer/replace-components/image/types.ts new file mode 100644 index 000000000..c6bca5350 --- /dev/null +++ b/src/components/editor/markdown-renderer/replace-components/image/types.ts @@ -0,0 +1,3 @@ +export interface ImageProxyResponse { + src: string +} diff --git a/src/redux/backend-config/reducers.ts b/src/redux/backend-config/reducers.ts index 11af19382..90b916169 100644 --- a/src/redux/backend-config/reducers.ts +++ b/src/redux/backend-config/reducers.ts @@ -30,6 +30,7 @@ export const initialState: BackendConfig = { oauth2: '', saml: '' }, + useImageProxy: false, specialLinks: { privacy: '', termsOfUse: '',