diff --git a/src/api/file-proxy.api.js b/src/api/file-proxy.api.js index a14104e89..1e73b53a6 100644 --- a/src/api/file-proxy.api.js +++ b/src/api/file-proxy.api.js @@ -1,4 +1,3 @@ -import axios from 'axios' import { isString } from 'lodash' import { getServiceProxyBaseUrl } from '@/config/baseUrl.config' @@ -57,40 +56,3 @@ export function proxifyUrl(url) { } return `${getServiceProxyBaseUrl()}${fileAsPath}` } - -/** - * Get a file through our service-proxy backend, taking care of CORS headers in the process. - * - * That means that a file for which there is no defined CORS header will still be accessible through - * this function (i.e. Dropbox/name your cloud share links) - * - * @param {String} fileUrl - * @param {Object} [options] - * @param {Number} [options.timeout] How long should the call wait before timing out - * @returns {Promise} A promise which resolve to the proxy response - */ -export default function getFileThroughProxy(fileUrl, options = {}) { - const { timeout = null } = options - return new Promise((resolve, reject) => { - try { - axios({ - method: 'get', - url: proxifyUrl(fileUrl), - timeout, - }) - .then((response) => { - resolve(response) - }) - .catch((error) => { - log.error( - 'Error while accessing file URL through service-proxy', - fileUrl, - error - ) - reject(error) - }) - } catch (error) { - reject(error) - } - }) -} diff --git a/src/api/files.api.js b/src/api/files.api.js index f63f0c2ea..12629adc5 100644 --- a/src/api/files.api.js +++ b/src/api/files.api.js @@ -1,10 +1,11 @@ -import axios, { AxiosError } from 'axios' +import axios from 'axios' import FormData from 'form-data' import pako from 'pako' -import getFileThroughProxy from '@/api/file-proxy.api' +import { proxifyUrl } from '@/api/file-proxy.api' import { getServiceKmlBaseUrl } from '@/config/baseUrl.config' import log from '@/utils/logging' +import { isInternalUrl } from '@/utils/utils' /** * KML links @@ -312,8 +313,7 @@ export function loadKmlData(kmlLayer) { new Error(`No file URL defined in this KML layer, cannot load data ${kmlLayer.id}`) ) } - axios - .get(kmlLayer.kmlFileUrl) + getFileFromUrl(kmlLayer.kmlFileUrl) .then((response) => { if (response.status === 200 && response.data) { resolve(response.data) @@ -324,19 +324,54 @@ export function loadKmlData(kmlLayer) { } }) .catch((error) => { - if (error instanceof AxiosError) { - getFileThroughProxy(kmlLayer.kmlFileUrl) - .then((response) => { - resolve(response.data) - }) - .catch((error) => { - reject(error) - }) - } else { - const msg = `Failed to load KML data: ${error}` - log.error(msg) - reject(new Error(msg)) - } + const msg = `Failed to load KML data: ${error}` + log.error(msg) + reject(new Error(msg)) }) }) } + +/** + * Generic function to load a file from a given URL. + * + * When the URL is not an internal url and it doesn't support CORS or use HTTP it is sent over a + * proxy. + * + * @param {string} url URL to fetch + * @param {Number} [options.timeout] How long should the call wait before timing out + * @returns {Promise>} + */ +export async function getFileFromUrl(url, options = {}) { + const { timeout = null } = options + if (/^https?:\/\/localhost/.test(url) || isInternalUrl(url)) { + // don't go through proxy if it is on localhost or the internal server + return axios.get(url, { timeout }) + } else if (url.startsWith('http://')) { + // HTTP request goes through the proxy + return axios.get(proxifyUrl(url), { timeout }) + } + + // For other urls we need to check if they support CORS + let supportCORS = false + try { + // unfortunately we cannot do a real preflight call using options because browser don't + // allow to set the Access-Control-* headers ! Also there is no way to find out if a request + // is failing due to network reason or due to CORS issue, + // see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors + // Therefore here we try to get the resource using head instead + await axios.head(url, { timeout }) + supportCORS = true + } catch (error) { + log.error( + `URL ${url} failed with ${error}. It might be due to CORS issue, ` + + `therefore the request will be fallback to the service-proxy` + ) + } + + if (supportCORS) { + // Server support CORS + return axios.get(url, { timeout }) + } + // server don't support CORS use proxy + return axios.get(proxifyUrl(url), { timeout }) +} diff --git a/src/config/baseUrl.config.js b/src/config/baseUrl.config.js index 0c9d0b79d..4f1e105a8 100644 --- a/src/config/baseUrl.config.js +++ b/src/config/baseUrl.config.js @@ -206,3 +206,6 @@ export function get3dTilesBaseUrl() { export function getVectorTilesBaseUrl() { return getBaseUrl('vectorTiles') } + +export const internalDomainRegex = + import.meta.env.VITE_APP_INTERNAL_DOMAIN_REGEX ?? /^https:\/\/[^/]*(bgdi|admin)\.ch/ diff --git a/src/modules/menu/components/advancedTools/ImportFile/ImportFileOnlineTab.vue b/src/modules/menu/components/advancedTools/ImportFile/ImportFileOnlineTab.vue index 2773f8fb2..25d594cea 100644 --- a/src/modules/menu/components/advancedTools/ImportFile/ImportFileOnlineTab.vue +++ b/src/modules/menu/components/advancedTools/ImportFile/ImportFileOnlineTab.vue @@ -1,9 +1,9 @@