Add support for image-proxies by (optional) piping of image urls through the backend (#315)

* Added config property for image proxies

* Added API call and image url replacing

* Added comment explaining why a local function is needed inside the useEffect

* Added CHANGELOG entry

* Changed wording of the CHANGELOG sentence

* Changed CHANGELOG entry

Co-Authored-By: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

* Removed fallback to original src

* Removed unnecessary API call for empty src URLs

* Simplify image url fetching

* Refactored imageframe to avoid rerendering of images

Co-Authored-By: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

* Renamed config property to useImageProxy

Co-authored-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
This commit is contained in:
Erik Michelson 2020-07-29 22:28:32 +02:00 committed by GitHub
parent 7b8243997c
commit 9c19bb1d9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 46 additions and 3 deletions

View file

@ -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 '@ <custom string>' or '@ <custom logo>' 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

View file

@ -26,6 +26,7 @@
"oauth2": "Olaf2",
"saml": "aufSAMLn.de"
},
"useImageProxy": false,
"specialLinks": {
"privacy": "https://example.com/privacy",
"termsOfUse": "https://example.com/termsOfUse",

View file

@ -4,6 +4,7 @@ export interface BackendConfig {
branding: BrandingConfig,
banner: BannerConfig,
customAuthNames: CustomAuthNames,
useImageProxy: boolean,
specialLinks: SpecialLinks,
version: BackendVersion,
}

15
src/api/imageProxy.ts Normal file
View file

@ -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<ImageProxyResponse> => {
const response = await fetch(getBackendUrl() + '/media/proxy', {
...defaultFetchConfig,
method: 'POST',
body: JSON.stringify({
src: imageUrl
})
})
expectResponseCode(response)
return await response.json() as Promise<ImageProxyResponse>
}

View file

@ -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<React.ImgHTMLAttributes<HTMLImageElement>> = ({ 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 (
<img alt={alt} src={imageUrl} {...props}/>
)
}
export const ImageFrame: React.FC<React.ImgHTMLAttributes<HTMLImageElement>> = ({alt, ...props}) => {
return (
<img alt={alt} {...props}/>
<img alt={alt} src={src ?? ''} {...props}/>
)
}

View file

@ -0,0 +1,3 @@
export interface ImageProxyResponse {
src: string
}

View file

@ -30,6 +30,7 @@ export const initialState: BackendConfig = {
oauth2: '',
saml: ''
},
useImageProxy: false,
specialLinks: {
privacy: '',
termsOfUse: '',