mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-12 16:10:30 +02:00
fix(core): Fix health endpoint cross-origin requests (#28878)
This commit is contained in:
parent
2c60f42fd0
commit
b6eabb4ce5
|
|
@ -137,14 +137,16 @@ export abstract class AbstractServer {
|
|||
const healthPath = this.endpointHealth;
|
||||
const readinessPath = `${healthPath}/readiness`;
|
||||
|
||||
const healthMiddlewares = inDevelopment ? [corsMiddleware] : [];
|
||||
|
||||
// main health check should not care about DB connections
|
||||
this.app.get(healthPath, (_req, res) => {
|
||||
this.app.get(healthPath, ...healthMiddlewares, (_req, res) => {
|
||||
res.send({ status: 'ok' });
|
||||
});
|
||||
|
||||
const { connectionState } = this.dbConnection;
|
||||
|
||||
this.app.get(readinessPath, (_req, res) => {
|
||||
this.app.get(readinessPath, ...healthMiddlewares, (_req, res) => {
|
||||
const { connected, migrated } = connectionState;
|
||||
if (connected && migrated && this.fullyReady) {
|
||||
res.status(200).send({ status: 'ok' });
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import merge from 'lodash/merge';
|
|||
import { useBackendStatus } from './useBackendStatus';
|
||||
import { useBackendConnectionStore } from '@/app/stores/backendConnection.store';
|
||||
import { useSettingsStore } from '@/app/stores/settings.store';
|
||||
import { useRootStore } from '@n8n/stores/useRootStore';
|
||||
import { defaultSettings } from '@/__tests__/defaults';
|
||||
|
||||
const mockStartHeartbeat = vi.fn();
|
||||
|
|
@ -96,6 +97,27 @@ describe('useBackendStatus', () => {
|
|||
expect(mockStopHeartbeat).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should prepend backend origin to health URL when baseUrl is a full URL', async () => {
|
||||
const rootStore = useRootStore();
|
||||
vi.spyOn(rootStore, 'baseUrl', 'get').mockReturnValue('http://localhost:5678/');
|
||||
|
||||
mockFetch.mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({ status: 'ok' }),
|
||||
});
|
||||
|
||||
const wrapper = createWrapper();
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(mockFetch).toHaveBeenCalledWith('http://localhost:5678/internal/health', {
|
||||
cache: 'no-store',
|
||||
signal: expect.any(AbortSignal),
|
||||
});
|
||||
});
|
||||
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('should skip health checks in preview mode', async () => {
|
||||
settingsStore.setSettings(
|
||||
merge({}, defaultSettings, {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { onMounted, onUnmounted, ref } from 'vue';
|
|||
import { useBackendConnectionStore } from '@/app/stores/backendConnection.store';
|
||||
import { useHeartbeat } from '@/app/push-connection/useHeartbeat';
|
||||
import { useSettingsStore } from '@/app/stores/settings.store';
|
||||
import { useRootStore } from '@n8n/stores/useRootStore';
|
||||
|
||||
const HEALTH_CHECK_INTERVAL = 10000;
|
||||
const HEALTH_CHECK_TIMEOUT = 5000;
|
||||
|
|
@ -9,6 +10,7 @@ const HEALTH_CHECK_TIMEOUT = 5000;
|
|||
export function useBackendStatus() {
|
||||
const backendConnectionStore = useBackendConnectionStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const rootStore = useRootStore();
|
||||
const checking = ref(false);
|
||||
|
||||
/**
|
||||
|
|
@ -22,8 +24,15 @@ export function useBackendStatus() {
|
|||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), HEALTH_CHECK_TIMEOUT);
|
||||
|
||||
// When baseUrl is a full URL (e.g. http://localhost:5678/ in dev mode),
|
||||
// extract the origin so the health request targets the backend directly.
|
||||
// When baseUrl is a relative path (e.g. /), the request goes to the current host.
|
||||
const base = rootStore.baseUrl;
|
||||
const origin = base.startsWith('http') ? new URL(base).origin : '';
|
||||
const healthUrl = origin + settingsStore.endpointHealth;
|
||||
|
||||
try {
|
||||
const response = await fetch(settingsStore.endpointHealth, {
|
||||
const response = await fetch(healthUrl, {
|
||||
cache: 'no-store',
|
||||
signal: controller.signal,
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user