fix: production CSRF, ProxyFix, and SSE streaming issues
This commit is contained in:
@@ -2,8 +2,9 @@ import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { Mail } from 'lucide-react';
|
||||
import { getApiClient } from '../services/api';
|
||||
|
||||
const API_BASE = import.meta.env.VITE_API_URL || '';
|
||||
const api = getApiClient();
|
||||
|
||||
export default function ForgotPasswordPage() {
|
||||
const { t } = useTranslation();
|
||||
@@ -18,13 +19,7 @@ export default function ForgotPasswordPage() {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/auth/forgot-password`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ email }),
|
||||
});
|
||||
if (!res.ok) throw new Error('Request failed');
|
||||
await api.post('/auth/forgot-password', { email });
|
||||
setSubmitted(true);
|
||||
} catch {
|
||||
setError(t('auth.forgotPassword.error'));
|
||||
|
||||
@@ -3,8 +3,9 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useSearchParams, useNavigate } from 'react-router-dom';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
import { KeyRound } from 'lucide-react';
|
||||
import { getApiClient } from '../services/api';
|
||||
|
||||
const API_BASE = import.meta.env.VITE_API_URL || '';
|
||||
const api = getApiClient();
|
||||
|
||||
export default function ResetPasswordPage() {
|
||||
const { t } = useTranslation();
|
||||
@@ -33,14 +34,7 @@ export default function ResetPasswordPage() {
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await fetch(`${API_BASE}/api/auth/reset-password`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ token, password }),
|
||||
});
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error || 'Reset failed');
|
||||
await api.post('/auth/reset-password', { token, password });
|
||||
setSuccess(true);
|
||||
setTimeout(() => navigate('/account'), 3000);
|
||||
} catch (err) {
|
||||
|
||||
@@ -412,13 +412,25 @@ export async function streamAssistantChat(
|
||||
payload: AssistantChatRequest,
|
||||
handlers: AssistantStreamHandlers = {}
|
||||
): Promise<AssistantChatResponse> {
|
||||
// Ensure a CSRF token cookie exists before streaming
|
||||
let csrfToken = getCookieValue(CSRF_COOKIE_NAME);
|
||||
if (!csrfToken) {
|
||||
await csrfBootstrapClient.get('/auth/csrf');
|
||||
csrfToken = getCookieValue(CSRF_COOKIE_NAME);
|
||||
}
|
||||
|
||||
const streamHeaders: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/event-stream',
|
||||
};
|
||||
if (csrfToken) {
|
||||
streamHeaders[CSRF_HEADER_NAME] = csrfToken;
|
||||
}
|
||||
|
||||
const response = await fetch('/api/assistant/chat/stream', {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/event-stream',
|
||||
},
|
||||
headers: streamHeaders,
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user