mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 03:06:31 -05:00
Revert "fix: replace class BaseUrlFromEnvExtractor"
This reverts commit 59bca4a81f
.
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
21ef5a0899
commit
7f5fd18e38
6 changed files with 105 additions and 95 deletions
|
@ -5,8 +5,8 @@
|
||||||
*/
|
*/
|
||||||
import { getNote } from '../../../api/notes'
|
import { getNote } from '../../../api/notes'
|
||||||
import { redirect } from 'next/navigation'
|
import { redirect } from 'next/navigation'
|
||||||
|
import { baseUrlFromEnvExtractor } from '../../../utils/base-url-from-env-extractor'
|
||||||
import { notFound } from 'next/navigation'
|
import { notFound } from 'next/navigation'
|
||||||
import { extractBaseUrls } from '../../../utils/base-url-from-env-extractor'
|
|
||||||
|
|
||||||
interface PageProps {
|
interface PageProps {
|
||||||
params: { id: string | undefined }
|
params: { id: string | undefined }
|
||||||
|
@ -16,7 +16,7 @@ interface PageProps {
|
||||||
* Redirects the user to the editor if the link is a root level direct link to a version 1 note.
|
* Redirects the user to the editor if the link is a root level direct link to a version 1 note.
|
||||||
*/
|
*/
|
||||||
const DirectLinkFallback = async ({ params }: PageProps) => {
|
const DirectLinkFallback = async ({ params }: PageProps) => {
|
||||||
const baseUrl = extractBaseUrls().editor
|
const baseUrl = baseUrlFromEnvExtractor.extractBaseUrls().editor
|
||||||
|
|
||||||
if (params.id === undefined) {
|
if (params.id === undefined) {
|
||||||
notFound()
|
notFound()
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { MotdModal } from '../../components/global-dialogs/motd-modal/motd-modal
|
||||||
import { DarkMode } from '../../components/layout/dark-mode/dark-mode'
|
import { DarkMode } from '../../components/layout/dark-mode/dark-mode'
|
||||||
import { UiNotificationBoundary } from '../../components/notifications/ui-notification-boundary'
|
import { UiNotificationBoundary } from '../../components/notifications/ui-notification-boundary'
|
||||||
import { StoreProvider } from '../../redux/store-provider'
|
import { StoreProvider } from '../../redux/store-provider'
|
||||||
import { extractBaseUrls } from '../../utils/base-url-from-env-extractor'
|
import { baseUrlFromEnvExtractor } from '../../utils/base-url-from-env-extractor'
|
||||||
import { configureLuxon } from '../../utils/configure-luxon'
|
import { configureLuxon } from '../../utils/configure-luxon'
|
||||||
import type { Metadata } from 'next'
|
import type { Metadata } from 'next'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
@ -20,7 +20,7 @@ import { getConfig } from '../../api/config'
|
||||||
configureLuxon()
|
configureLuxon()
|
||||||
|
|
||||||
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
const baseUrls = extractBaseUrls()
|
const baseUrls = baseUrlFromEnvExtractor.extractBaseUrls()
|
||||||
const frontendConfig = await getConfig(baseUrls.editor)
|
const frontendConfig = await getConfig(baseUrls.editor)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -8,12 +8,12 @@ import { ApplicationLoader } from '../../components/application-loader/applicati
|
||||||
import { BaseUrlContextProvider } from '../../components/common/base-url/base-url-context-provider'
|
import { BaseUrlContextProvider } from '../../components/common/base-url/base-url-context-provider'
|
||||||
import { FrontendConfigContextProvider } from '../../components/common/frontend-config-context/frontend-config-context-provider'
|
import { FrontendConfigContextProvider } from '../../components/common/frontend-config-context/frontend-config-context-provider'
|
||||||
import { StoreProvider } from '../../redux/store-provider'
|
import { StoreProvider } from '../../redux/store-provider'
|
||||||
import { extractBaseUrls } from '../../utils/base-url-from-env-extractor'
|
import { baseUrlFromEnvExtractor } from '../../utils/base-url-from-env-extractor'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { getConfig } from '../../api/config'
|
import { getConfig } from '../../api/config'
|
||||||
|
|
||||||
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
export default async function RootLayout({ children }: { children: React.ReactNode }) {
|
||||||
const baseUrls = extractBaseUrls()
|
const baseUrls = baseUrlFromEnvExtractor.extractBaseUrls()
|
||||||
const frontendConfig = await getConfig(baseUrls.renderer)
|
const frontendConfig = await getConfig(baseUrls.renderer)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import type { NextRequest } from 'next/server'
|
import type { NextRequest } from 'next/server'
|
||||||
import { extractBaseUrls } from './utils/base-url-from-env-extractor'
|
import { baseUrlFromEnvExtractor } from './utils/base-url-from-env-extractor'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Next.js middleware that checks if the expected and the current origin align.
|
* Next.js middleware that checks if the expected and the current origin align.
|
||||||
|
@ -51,5 +51,9 @@ const determineOriginFromHeaders = (headers: Headers): string | undefined => {
|
||||||
* @param request The current request
|
* @param request The current request
|
||||||
*/
|
*/
|
||||||
const determineExpectedOrigin = (request: NextRequest): string => {
|
const determineExpectedOrigin = (request: NextRequest): string => {
|
||||||
return new URL(request.nextUrl.pathname === '/render' ? extractBaseUrls().renderer : extractBaseUrls().editor).origin
|
return new URL(
|
||||||
|
request.nextUrl.pathname === '/render'
|
||||||
|
? baseUrlFromEnvExtractor.extractBaseUrls().renderer
|
||||||
|
: baseUrlFromEnvExtractor.extractBaseUrls().editor
|
||||||
|
).origin
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,22 +3,15 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
import { BaseUrlFromEnvExtractor } from './base-url-from-env-extractor'
|
||||||
import type { BaseUrls } from '../components/common/base-url/base-url-context-provider'
|
|
||||||
|
|
||||||
describe('BaseUrlFromEnvExtractor', () => {
|
describe('BaseUrlFromEnvExtractor', () => {
|
||||||
let extractBaseUrls: () => BaseUrls
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
jest.resetModules()
|
|
||||||
extractBaseUrls = (await import('./base-url-from-env-extractor')).extractBaseUrls
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return the base urls if both are valid urls', () => {
|
it('should return the base urls if both are valid urls', () => {
|
||||||
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
||||||
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org/'
|
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org/'
|
||||||
|
const sut = new BaseUrlFromEnvExtractor()
|
||||||
|
|
||||||
expect(extractBaseUrls()).toStrictEqual({
|
expect(sut.extractBaseUrls()).toStrictEqual({
|
||||||
renderer: 'https://renderer.example.org/',
|
renderer: 'https://renderer.example.org/',
|
||||||
editor: 'https://editor.example.org/'
|
editor: 'https://editor.example.org/'
|
||||||
})
|
})
|
||||||
|
@ -27,29 +20,33 @@ describe('BaseUrlFromEnvExtractor', () => {
|
||||||
it('should return an empty optional if no var is set', () => {
|
it('should return an empty optional if no var is set', () => {
|
||||||
process.env.HD_BASE_URL = undefined
|
process.env.HD_BASE_URL = undefined
|
||||||
process.env.HD_RENDERER_BASE_URL = undefined
|
process.env.HD_RENDERER_BASE_URL = undefined
|
||||||
|
const sut = new BaseUrlFromEnvExtractor()
|
||||||
|
|
||||||
expect(() => extractBaseUrls()).toThrow()
|
expect(() => sut.extractBaseUrls()).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should return an empty optional if editor base url isn't an URL", () => {
|
it("should return an empty optional if editor base url isn't an URL", () => {
|
||||||
process.env.HD_BASE_URL = 'bibedibabedibu'
|
process.env.HD_BASE_URL = 'bibedibabedibu'
|
||||||
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org/'
|
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org/'
|
||||||
|
const sut = new BaseUrlFromEnvExtractor()
|
||||||
|
|
||||||
expect(() => extractBaseUrls()).toThrow()
|
expect(() => sut.extractBaseUrls()).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should return an empty optional if renderer base url isn't an URL", () => {
|
it("should return an empty optional if renderer base url isn't an URL", () => {
|
||||||
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
||||||
process.env.HD_RENDERER_BASE_URL = 'bibedibabedibu'
|
process.env.HD_RENDERER_BASE_URL = 'bibedibabedibu'
|
||||||
|
const sut = new BaseUrlFromEnvExtractor()
|
||||||
|
|
||||||
expect(() => extractBaseUrls()).toThrow()
|
expect(() => sut.extractBaseUrls()).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should return an optional if editor base url isn't ending with a slash", () => {
|
it("should return an optional if editor base url isn't ending with a slash", () => {
|
||||||
process.env.HD_BASE_URL = 'https://editor.example.org'
|
process.env.HD_BASE_URL = 'https://editor.example.org'
|
||||||
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org/'
|
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org/'
|
||||||
|
const sut = new BaseUrlFromEnvExtractor()
|
||||||
|
|
||||||
expect(extractBaseUrls()).toStrictEqual({
|
expect(sut.extractBaseUrls()).toStrictEqual({
|
||||||
renderer: 'https://renderer.example.org/',
|
renderer: 'https://renderer.example.org/',
|
||||||
editor: 'https://editor.example.org/'
|
editor: 'https://editor.example.org/'
|
||||||
})
|
})
|
||||||
|
@ -58,8 +55,9 @@ describe('BaseUrlFromEnvExtractor', () => {
|
||||||
it("should return an optional if renderer base url isn't ending with a slash", () => {
|
it("should return an optional if renderer base url isn't ending with a slash", () => {
|
||||||
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
||||||
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org'
|
process.env.HD_RENDERER_BASE_URL = 'https://renderer.example.org'
|
||||||
|
const sut = new BaseUrlFromEnvExtractor()
|
||||||
|
|
||||||
expect(extractBaseUrls()).toStrictEqual({
|
expect(sut.extractBaseUrls()).toStrictEqual({
|
||||||
renderer: 'https://renderer.example.org/',
|
renderer: 'https://renderer.example.org/',
|
||||||
editor: 'https://editor.example.org/'
|
editor: 'https://editor.example.org/'
|
||||||
})
|
})
|
||||||
|
@ -68,8 +66,9 @@ describe('BaseUrlFromEnvExtractor', () => {
|
||||||
it('should copy editor base url to renderer base url if renderer base url is omitted', () => {
|
it('should copy editor base url to renderer base url if renderer base url is omitted', () => {
|
||||||
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
process.env.HD_BASE_URL = 'https://editor.example.org/'
|
||||||
delete process.env.HD_RENDERER_BASE_URL
|
delete process.env.HD_RENDERER_BASE_URL
|
||||||
|
const sut = new BaseUrlFromEnvExtractor()
|
||||||
|
|
||||||
expect(extractBaseUrls()).toStrictEqual({
|
expect(sut.extractBaseUrls()).toStrictEqual({
|
||||||
renderer: 'https://editor.example.org/',
|
renderer: 'https://editor.example.org/',
|
||||||
editor: 'https://editor.example.org/'
|
editor: 'https://editor.example.org/'
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,81 +9,88 @@ import { isTestMode, isBuildTime } from './test-modes'
|
||||||
import { NoSubdirectoryAllowedError, parseUrl } from '@hedgedoc/commons'
|
import { NoSubdirectoryAllowedError, parseUrl } from '@hedgedoc/commons'
|
||||||
import { Optional } from '@mrdrogdrog/optional'
|
import { Optional } from '@mrdrogdrog/optional'
|
||||||
|
|
||||||
let baseUrls: BaseUrls | undefined = undefined
|
|
||||||
const logger = new Logger('Base URL Configuration')
|
|
||||||
|
|
||||||
function extractUrlFromEnvVar(envVarName: string, envVarValue: string | undefined): Optional<URL> {
|
|
||||||
try {
|
|
||||||
return parseUrl(envVarValue)
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof NoSubdirectoryAllowedError) {
|
|
||||||
logger.error(error.message)
|
|
||||||
return Optional.empty()
|
|
||||||
} else {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractEditorBaseUrlFromEnv(): Optional<URL> {
|
|
||||||
const envValue = extractUrlFromEnvVar('HD_BASE_URL', process.env.HD_BASE_URL)
|
|
||||||
if (envValue.isEmpty()) {
|
|
||||||
logger.error("HD_BASE_URL isn't a valid URL!")
|
|
||||||
}
|
|
||||||
return envValue
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractRendererBaseUrlFromEnv(editorBaseUrl: URL): Optional<URL> {
|
|
||||||
if (isTestMode) {
|
|
||||||
logger.info('Test mode activated. Using editor base url for renderer.')
|
|
||||||
return Optional.of(editorBaseUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process.env.HD_RENDERER_BASE_URL) {
|
|
||||||
logger.info('HD_RENDERER_BASE_URL is unset. Using editor base url for renderer.')
|
|
||||||
return Optional.of(editorBaseUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
return extractUrlFromEnvVar('HD_RENDERER_BASE_URL', process.env.HD_RENDERER_BASE_URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
function renewBaseUrls(): BaseUrls {
|
|
||||||
return extractEditorBaseUrlFromEnv()
|
|
||||||
.flatMap((editorBaseUrl) =>
|
|
||||||
extractRendererBaseUrlFromEnv(editorBaseUrl).map((rendererBaseUrl) => {
|
|
||||||
return {
|
|
||||||
editor: editorBaseUrl.toString(),
|
|
||||||
renderer: rendererBaseUrl.toString()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.orElseThrow(() => new Error('couldnt parse env vars'))
|
|
||||||
}
|
|
||||||
|
|
||||||
function logBaseUrls() {
|
|
||||||
if (baseUrls === undefined) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger.info('Editor base URL', baseUrls.editor.toString())
|
|
||||||
logger.info('Renderer base URL', baseUrls.renderer.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the editor and renderer base urls from the environment variables.
|
* Extracts and caches the editor and renderer base urls from the environment variables.
|
||||||
*
|
|
||||||
* @return An {@link Optional} with the base urls.
|
|
||||||
*/
|
*/
|
||||||
export function extractBaseUrls(): BaseUrls {
|
export class BaseUrlFromEnvExtractor {
|
||||||
if (isBuildTime) {
|
private baseUrls: BaseUrls | undefined
|
||||||
return {
|
private readonly logger = new Logger('Base URL Configuration')
|
||||||
editor: 'https://example.org/',
|
|
||||||
renderer: 'https://example.org/'
|
private extractUrlFromEnvVar(envVarName: string, envVarValue: string | undefined): Optional<URL> {
|
||||||
|
try {
|
||||||
|
return parseUrl(envVarValue)
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof NoSubdirectoryAllowedError) {
|
||||||
|
this.logger.error(error.message)
|
||||||
|
return Optional.empty()
|
||||||
|
} else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseUrls === undefined) {
|
private extractEditorBaseUrlFromEnv(): Optional<URL> {
|
||||||
baseUrls = renewBaseUrls()
|
const envValue = this.extractUrlFromEnvVar('HD_BASE_URL', process.env.HD_BASE_URL)
|
||||||
logBaseUrls()
|
if (envValue.isEmpty()) {
|
||||||
|
this.logger.error("HD_BASE_URL isn't a valid URL!")
|
||||||
|
}
|
||||||
|
return envValue
|
||||||
|
}
|
||||||
|
|
||||||
|
private extractRendererBaseUrlFromEnv(editorBaseUrl: URL): Optional<URL> {
|
||||||
|
if (isTestMode) {
|
||||||
|
this.logger.info('Test mode activated. Using editor base url for renderer.')
|
||||||
|
return Optional.of(editorBaseUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!process.env.HD_RENDERER_BASE_URL) {
|
||||||
|
this.logger.info('HD_RENDERER_BASE_URL is unset. Using editor base url for renderer.')
|
||||||
|
return Optional.of(editorBaseUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.extractUrlFromEnvVar('HD_RENDERER_BASE_URL', process.env.HD_RENDERER_BASE_URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
private renewBaseUrls(): BaseUrls {
|
||||||
|
return this.extractEditorBaseUrlFromEnv()
|
||||||
|
.flatMap((editorBaseUrl) =>
|
||||||
|
this.extractRendererBaseUrlFromEnv(editorBaseUrl).map((rendererBaseUrl) => {
|
||||||
|
return {
|
||||||
|
editor: editorBaseUrl.toString(),
|
||||||
|
renderer: rendererBaseUrl.toString()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.orElseThrow(() => new Error('couldnt parse env vars'))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the editor and renderer base urls from the environment variables.
|
||||||
|
*
|
||||||
|
* @return An {@link Optional} with the base urls.
|
||||||
|
*/
|
||||||
|
public extractBaseUrls(): BaseUrls {
|
||||||
|
if (isBuildTime) {
|
||||||
|
return {
|
||||||
|
editor: 'https://example.org/',
|
||||||
|
renderer: 'https://example.org/'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.baseUrls === undefined) {
|
||||||
|
this.baseUrls = this.renewBaseUrls()
|
||||||
|
this.logBaseUrls()
|
||||||
|
}
|
||||||
|
return this.baseUrls
|
||||||
|
}
|
||||||
|
|
||||||
|
private logBaseUrls() {
|
||||||
|
if (this.baseUrls === undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.logger.info('Editor base URL', this.baseUrls.editor.toString())
|
||||||
|
this.logger.info('Renderer base URL', this.baseUrls.renderer.toString())
|
||||||
}
|
}
|
||||||
return baseUrls
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const baseUrlFromEnvExtractor = new BaseUrlFromEnvExtractor()
|
||||||
|
|
Loading…
Reference in a new issue