Cross-Origin Request Blocked with status code: 200, when generating document on react with Docxtemplater
23:54 21 Nov 2024

I am having trouble generating document on localhost webpage. Project is with laravel 11 backend (with breeze starter-kit) and vite-react frontend.

When trying to generate it, I get error in console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/Template_Doc.docx. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.

My backend port is on port 8000, and web port on 5173.

I have seperate folders for backend and frontend

I have saved template document in directory "/backend/public/Template_Doc.docx"

In backend/ I have server.js:

const express = require("express");
const path = require("path");
const fs = require("fs");
const cors = require("cors");

const app = express();
const PORT = 8000;

// Global CORS middleware
app.use(
    cors({
        origin: "http://localhost:5173",
        credentials: true,
        methods: ["GET", "POST", "OPTIONS"],
        allowedHeaders: ["Content-Type", "Authorization", "Accept"],
        exposedHeaders: ["Content-Disposition"],
    })
);

// Pre-flight requests
app.options("*", cors());

// Middleware for all routes to ensure CORS headers
app.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "http://localhost:5173");
    res.header("Access-Control-Allow-Credentials", "true");
    res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    res.header(
        "Access-Control-Allow-Headers",
        "Content-Type, Authorization, Accept"
    );
    res.header("Access-Control-Expose-Headers", "Content-Disposition");
    next();
});

// Route for template file
app.get("/storage/Template_Doc.docx", (req, res) => {
    const filePath = path.join(
        __dirname,
        "public",
        "storage",
        "Template_Doc.docx"
    );
    console.log("Attempting to serve template from:", filePath);

    try {
        if (fs.existsSync(filePath)) {
            const stats = fs.statSync(filePath);
            console.log("File found:", {
                size: stats.size,
                permissions: stats.mode.toString(8),
            });

            // Set necessary headers
            res.header(
                "Content-Type",
                "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
            );
            res.header(
                "Content-Disposition",
                "attachment; filename=Template_Doc.docx"
            );

            // Send file
            res.sendFile(filePath, (err) => {
                if (err) {
                    console.error("Error sending file:", err);
                    res.status(500).send("Error sending file");
                } else {
                    console.log("File sent successfully");
                }
            });
        } else {
            console.error("File not found at:", filePath);
            res.status(404).send("File not found");
        }
    } catch (error) {
        console.error("Error accessing file:", error);
        res.status(500).send("Server error");
    }
});

// Start server
app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);

    // Check template on startup
    const templatePath = path.join(
        __dirname,
        "public",
        "storage",
        "Template_Doc.docx"
    );
    if (fs.existsSync(templatePath)) {
        const stats = fs.statSync(templatePath);
        console.log("Template file ready:", {
            path: templatePath,
            size: stats.size,
            permissions: stats.mode.toString(8),
        });
    } else {
        console.error("Template file not found at:", templatePath);
    }
});

In backend/cors.php I have setup:

'paths' => ['register', 'login', 'logout','api/*', 'Template_Doc.docx', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['http://localhost:5173'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true

In directory frontend/src/components/DocumentPage.jsx, I have functions:

loadFile:

function loadFile(url, callback) {
    const fullUrl = `http://localhost:8000${url}`;
    console.log('Attempting to load file from:', fullUrl);

    fetch(fullUrl, {
        method: 'GET',
        credentials: 'include',
        headers: {
            'Accept': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        },
        mode: 'cors',
    })
        .then((response) => {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.arrayBuffer();
        })
        .then((buffer) => {
            console.log('Template loaded successfully, size:', buffer.byteLength);
            callback(null, buffer);
        })
        .catch((error) => {
            console.error('Error loading template:', error);
            alert('Error loading template. Please check if the server is running and the file is accessible.');
            callback(error);
        });
}

Also generateDocument:

const generateDocument = async (e) => {
    e.preventDefault();
    console.log('Starting document generation...');

    try {
        // Use the direct path since we're handling it in the loadFile function
        loadFile('/Template_Doc.docx', function (error, content) {
            if (error) {
                console.error('Error loading file:', error);
                return;
            }
            const zip = new PizZip(content);
            const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true });
            doc.render(formData);
            const out = doc.getZip().generate({
                type: 'blob',
                mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            });
            saveAs(out, 'output.docx');
        });
    } catch (error) {
        console.error('Error in generate document:', error);
        console.error('Error details:', {
            message: error.message,
            stack: error.stack
        });
        alert('Error in document generation process. Please check the console for details.');
    }
};

I cannot find any solutions to this type of error online. Could anyone perhaps offer advice?

javascript php laravel express docxtemplater