Files
outline/server/utils/fetch.ts
Tom Moor f46921275d fix: copy pasting the content from some medium into outline does not get the images (#8472)
* fix: Files from local storage provider sometimes returned with incorrect content type

* fix: attachments.createFromUrl response values incorrect for successful upload

* fix: Reduce liklihood of image download requests being blocked on server

* fix: Content with HTML images should never be considered as markdown

* fix: Image caption sometimes uncentered

* test
2025-02-17 11:54:13 -08:00

52 lines
1.6 KiB
TypeScript

/* eslint-disable no-restricted-imports */
import fetchWithProxy from "fetch-with-proxy";
import nodeFetch, { RequestInit, Response } from "node-fetch";
import { useAgent } from "request-filtering-agent";
import env from "@server/env";
import Logger from "@server/logging/Logger";
export type { RequestInit } from "node-fetch";
/**
* Fake Chrome user agent string for use in fetch requests to
* improve reliability.
*/
export const chromeUserAgent =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36";
/**
* Wrapper around fetch that uses the request-filtering-agent in cloud hosted
* environments to filter malicious requests, and the fetch-with-proxy library
* in self-hosted environments to allow for request from behind a proxy.
*
* @param url The url to fetch
* @param init The fetch init object
* @returns The response
*/
export default async function fetch(
url: string,
init?: RequestInit
): Promise<Response> {
// In self-hosted, webhooks support proxying and are also allowed to connect
// to internal services, so use fetchWithProxy without the filtering agent.
const fetchMethod = env.isCloudHosted ? nodeFetch : fetchWithProxy;
Logger.silly("http", `Network request to ${url}`, init);
const response = await fetchMethod(url, {
...init,
agent: env.isCloudHosted ? useAgent(url) : undefined,
});
if (!response.ok) {
Logger.silly("http", `Network request failed`, {
url,
status: response.status,
statusText: response.statusText,
headers: response.headers.raw(),
});
}
return response;
}