diff --git a/assets/vue/config/api.js b/assets/vue/config/api.js index ae613c7c90d..428301743ef 100644 --- a/assets/vue/config/api.js +++ b/assets/vue/config/api.js @@ -4,7 +4,6 @@ import axios from "axios" * @type {axios.AxiosInstance} */ const instance = axios.create({ - baseURL: window.location.origin, headers: { Accept: "application/ld+json", }, diff --git a/assets/vue/config/entrypoint.js b/assets/vue/config/entrypoint.js index 01dab83ccc5..8571c61a1fe 100644 --- a/assets/vue/config/entrypoint.js +++ b/assets/vue/config/entrypoint.js @@ -1,3 +1,3 @@ -export const ENTRYPOINT = window.location.origin + "/api/" +export const ENTRYPOINT = "/api/" //export const ENTRYPOINT = process.env.APP_API_PLATFORM_URL; diff --git a/assets/vue/main.js b/assets/vue/main.js index 40d291b3e79..7fe53307c77 100644 --- a/assets/vue/main.js +++ b/assets/vue/main.js @@ -263,6 +263,18 @@ installHttpErrors({ on500: (err) => console.error("Server error", err?.response?.data?.detail || "Server error"), }) +// Fix mixed-content caused by server-generated http:// URLs when behind a +// TLS-terminating reverse proxy whose IP is not listed in TRUSTED_PROXIES. +// If the page was loaded over HTTPS, force every absolute http:// request URL +// to use https:// so the browser does not block it as mixed content. +axios.interceptors.request.use((config) => { + if (window.location.protocol === "https:" && config.url && config.url.startsWith("http://")) { + config.url = config.url.replace(/^http:\/\//, "https://") + } + + return config +}) + // Add cid/sid/gid automatically to every axios request to /api/* axios.interceptors.request.use((config) => { const sp = new URLSearchParams(window.location.search) diff --git a/assets/vue/services/languageService.js b/assets/vue/services/languageService.js index 180039dd5fc..031a01e35dd 100644 --- a/assets/vue/services/languageService.js +++ b/assets/vue/services/languageService.js @@ -3,7 +3,7 @@ import { ENTRYPOINT } from "../config/entrypoint" const legalExtensions = { async findAllAvailable() { - const url = new URL(`${ENTRYPOINT}languages`) + const url = new URL(`${ENTRYPOINT}languages`, window.location.origin) url.searchParams.append("available", "true") try { const response = await fetch(url.toString()) diff --git a/assets/vue/utils/fetch.js b/assets/vue/utils/fetch.js index c831e51a2b4..61598487928 100644 --- a/assets/vue/utils/fetch.js +++ b/assets/vue/utils/fetch.js @@ -92,7 +92,14 @@ export default function (id, options = {}) { console.log("ready to fetch") - return global.fetch(new URL(id, entryPoint), options).then((response) => { + // Resolve the entrypoint against the page origin at call time so ENTRYPOINT + // can be a relative path ("/api/"). Then force the page protocol to prevent + // mixed-content from server-generated http:// IRIs behind a reverse proxy. + const base = new URL(entryPoint, window.location.origin) + const url = new URL(id, base) + url.protocol = window.location.protocol + + return global.fetch(url, options).then((response) => { console.log(response, "global.fetch") if (response.ok) {