From 7055f135bb911bf2f9c557a08d2daecd34a18255 Mon Sep 17 00:00:00 2001 From: Connor Yoh Date: Tue, 1 Jul 2025 14:22:19 +0100 Subject: [PATCH] Working build --- frontend/src-tauri/src/lib.rs | 5 ++-- frontend/src-tauri/tauri.conf.json | 7 +++-- frontend/src/services/backendService.ts | 3 ++- frontend/src/tools/Compress.tsx | 3 ++- frontend/src/tools/Merge.tsx | 3 ++- frontend/src/tools/Split.tsx | 3 ++- frontend/src/utils/api.ts | 26 +++++++++++++++++++ frontend/vite.config.ts | 25 +++++++++++++++++- .../software/SPDF/config/WebMvcConfig.java | 15 +++++++++++ 9 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 frontend/src/utils/api.ts diff --git a/frontend/src-tauri/src/lib.rs b/frontend/src-tauri/src/lib.rs index e5745399f..c1ae161fb 100644 --- a/frontend/src-tauri/src/lib.rs +++ b/frontend/src-tauri/src/lib.rs @@ -4,7 +4,6 @@ use tauri::{RunEvent, WindowEvent}; // Store backend process handle and logs globally use std::sync::Mutex; -use std::sync::Arc; use std::collections::VecDeque; static BACKEND_PROCESS: Mutex> = Mutex::new(None); @@ -538,13 +537,13 @@ pub fn run() { .expect("error while building tauri application") .run(|app_handle, event| { match event { - RunEvent::ExitRequested { api, .. } => { + RunEvent::ExitRequested { .. } => { add_log("🔄 App exit requested, cleaning up...".to_string()); cleanup_backend(); // Use Tauri's built-in cleanup app_handle.cleanup_before_exit(); } - RunEvent::WindowEvent { event: WindowEvent::CloseRequested { api, .. }, .. } => { + RunEvent::WindowEvent { event: WindowEvent::CloseRequested {.. }, .. } => { add_log("🔄 Window close requested, cleaning up...".to_string()); cleanup_backend(); // Allow the window to close diff --git a/frontend/src-tauri/tauri.conf.json b/frontend/src-tauri/tauri.conf.json index 0adfa650e..1eaa8f912 100644 --- a/frontend/src-tauri/tauri.conf.json +++ b/frontend/src-tauri/tauri.conf.json @@ -18,10 +18,8 @@ "resizable": true, "fullscreen": false } - ], - "security": { - "csp": null - } + ] + }, "bundle": { "active": true, @@ -40,5 +38,6 @@ "shell": { "open": true } + } } diff --git a/frontend/src/services/backendService.ts b/frontend/src/services/backendService.ts index 3dcc7b3d8..beff78a2d 100644 --- a/frontend/src/services/backendService.ts +++ b/frontend/src/services/backendService.ts @@ -1,4 +1,5 @@ import { invoke } from '@tauri-apps/api/core'; +import { getApiBaseUrl } from '../utils/api'; export class BackendService { private static instance: BackendService; @@ -51,7 +52,7 @@ export class BackendService { } getBackendUrl(): string { - return 'http://localhost:8080'; + return getApiBaseUrl() || 'http://localhost:8080'; } async makeApiCall(endpoint: string, options?: RequestInit): Promise { diff --git a/frontend/src/tools/Compress.tsx b/frontend/src/tools/Compress.tsx index 8f8f4257b..7a6cba5c1 100644 --- a/frontend/src/tools/Compress.tsx +++ b/frontend/src/tools/Compress.tsx @@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next"; import { Stack, Slider, Group, Text, Button, Checkbox, TextInput, Paper } from "@mantine/core"; import { FileWithUrl } from "../types/file"; import { fileStorage } from "../services/fileStorage"; +import { makeApiUrl } from "../utils/api"; export interface CompressProps { files?: FileWithUrl[]; @@ -85,7 +86,7 @@ const CompressPdfPanel: React.FC = ({ formData.append("aggressive", aggressive.toString()); if (expectedSize) formData.append("expectedSize", expectedSize); - const res = await fetch("/api/v1/general/compress-pdf", { + const res = await fetch(makeApiUrl("/api/v1/general/compress-pdf"), { method: "POST", body: formData, }); diff --git a/frontend/src/tools/Merge.tsx b/frontend/src/tools/Merge.tsx index e9f528739..2161cadd0 100644 --- a/frontend/src/tools/Merge.tsx +++ b/frontend/src/tools/Merge.tsx @@ -4,6 +4,7 @@ import { useSearchParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { FileWithUrl } from "../types/file"; import { fileStorage } from "../services/fileStorage"; +import { makeApiUrl } from "../utils/api"; export interface MergePdfPanelProps { files: FileWithUrl[]; @@ -61,7 +62,7 @@ const MergePdfPanel: React.FC = ({ setErrorMessage(null); try { - const response = await fetch("/api/v1/general/merge-pdfs", { + const response = await fetch(makeApiUrl("/api/v1/general/merge-pdfs"), { method: "POST", body: formData, }); diff --git a/frontend/src/tools/Split.tsx b/frontend/src/tools/Split.tsx index 37b4efe8c..19c0c19a8 100644 --- a/frontend/src/tools/Split.tsx +++ b/frontend/src/tools/Split.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; import axios from "axios"; +import { makeApiUrl } from "../utils/api"; import { Button, Select, @@ -122,7 +123,7 @@ const SplitPdfPanel: React.FC = ({ setErrorMessage(null); try { - const response = await axios.post(endpoint, formData, { responseType: "blob" }); + const response = await axios.post(makeApiUrl(endpoint), formData, { responseType: "blob" }); const blob = new Blob([response.data], { type: "application/zip" }); const url = window.URL.createObjectURL(blob); setDownloadUrl(url); diff --git a/frontend/src/utils/api.ts b/frontend/src/utils/api.ts new file mode 100644 index 000000000..16333f8f6 --- /dev/null +++ b/frontend/src/utils/api.ts @@ -0,0 +1,26 @@ +export const getApiBaseUrl = (): string => { + const envUrl = import.meta.env.VITE_API_BASE_URL; + + // In development, use empty string to leverage Vite proxy + // In production/Tauri, use localhost:8080 directly + // if (envUrl !== undefined) { + // console.log(`Using API base URL from environment: ${envUrl}`); + // return envUrl; + // } + + // Fallback for development + console.log('Using default API base URL: http://localhost:8080'); + return 'http://localhost:8080'; +}; + +export const makeApiUrl = (endpoint: string): string => { + const baseUrl = getApiBaseUrl(); + + // If baseUrl is empty (development), return endpoint as-is for proxy + if (!baseUrl) { + return endpoint; + } + + // For production, combine base URL with endpoint + return `${baseUrl}${endpoint}`; +}; \ No newline at end of file diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index d957fa3f0..b62b4b3d8 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -2,8 +2,31 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; export default defineConfig({ + // prevent vite from obscuring rust errors + // clearScreen: false, + // // Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`. + // envPrefix: ['VITE_', 'TAURI_ENV_*'], + // build: { + // // Tauri uses Chromium on Windows and WebKit on macOS and Linux + // target: + // process.env.TAURI_ENV_PLATFORM == 'windows' + // ? 'chrome105' + // : 'safari13', + // // don't minify for debug builds + // minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false, + // // produce sourcemaps for debug builds + // sourcemap: !!process.env.TAURI_ENV_DEBUG, + // }, plugins: [react()], server: { + // make sure this port matches the devUrl port in tauri.conf.json file + port: 5173, + // Tauri expects a fixed port, fail if that port is not available + strictPort: true, + watch: { + // tell vite to ignore watching `src-tauri` + ignored: ['**/src-tauri/**'], + }, proxy: { '/api': { target: 'http://localhost:8080', @@ -12,4 +35,4 @@ export default defineConfig({ }, }, }, -}); +}); \ No newline at end of file diff --git a/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java b/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java index 63957fd0f..b86f7b3ec 100644 --- a/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java +++ b/src/main/java/stirling/software/SPDF/config/WebMvcConfig.java @@ -1,6 +1,7 @@ package stirling.software.SPDF.config; import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -26,4 +27,18 @@ public class WebMvcConfig implements WebMvcConfigurer { "file:" + InstallationPathConfig.getStaticPath(), "classpath:/static/"); // .setCachePeriod(0); // Optional: disable caching } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins( + "http://localhost:3000", + "http://localhost:5173", + "http://tauri.localhost", + "tauri://localhost", + "app://localhost", + "file://") + .allowedMethods("*") + .allowedHeaders("*"); + } }