node.jsexpresspostgethttp-proxy

Express.js proxied POST request does not work, returning timeout. The GET works just fine


I have my main script called index.js

require('dotenv').config();

const express = require("express");
const httpProxy = require('http-proxy');
const proxy = httpProxy.createProxyServer({});
const PORT = process.env.PORT || 3001;

const app = express();

app.use(express.json());  // Ensure JSON request bodies are parsed

// Log all incoming requests
app.use((req, res, next) => {
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
    next();
});

app.get("/api", (req, res) => {
    res.json({ message: "Hello from server!" });
    console.log('Handled /api request');
});

// Middleware for proxying to motchi process
app.use((req, res, next) => {
    if (req.url.startsWith('/get-user-data/')) {
        console.log(`Proxying GET request to motchi process: ${req.url}`);
        proxy.web(req, res, { target: 'http://localhost:5000' }, (error) => {
            if (error) {
                console.error('Proxy error:', error);
                res.status(500).send('Proxy Error');
            }
        });
    } else if (req.url.startsWith('/update-user-data')) {
        console.log(`Proxying POST request to motchi process: ${req.url}`);
        console.log('Request Body:', req.body); // Add logging here to inspect the request body

        proxy.web(req, res, { target: 'http://localhost:5000' }, (error) => {
            if (error) {
                console.error('Proxy error:', error);
                res.status(500).send('Proxy Error');
            } else {
                console.log('Proxying successful for:', req.url);
            }
        });
    } else {
        next(); // Continue to other routes handled by index
    }
});


// Start the server
app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
});

and my second script for working with POST/GET logic called motchi.js (some of it was removed)

const express = require("express");
const path = require("path");
const { MongoClient, ObjectId } = require("mongodb");
const server = express();
const port = process.env.PORT || 5000;
const gameName = "motchi";
const queries = {};

// Static file serving
//server.use(express.static(path.join(__dirname, 'backend')));

// Parse JSON bodies
server.use(express.json());

//Chat ID user client
server.get("/get-user-data/:chatId", async (req, res) => {
    const chatId = Number(req.params.chatId); // Ensure chatId is treated as a number
    console.log(`[${new Date().toISOString()}] Received request for user data: chatId = ${chatId}`);

    const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

    try {
        await client.connect();
        const db = client.db("myDatabase");
        console.log(`Connected to database. Searching for user with chatId: ${chatId}`);
        const user = await db.collection("users").findOne({ chatId: chatId });

        if (user) {
            console.log(`User data found for chatId ${chatId}:`, user);
            res.json(user);
        } else {
            console.log(`No user data found for chatId ${chatId}`);
            res.status(404).send("User not found");
        }
    } catch (err) {
        console.error(`Error fetching user data for chatId ${chatId}:`, err);
        res.status(500).send("Server error");
    } finally {
        await client.close();
        console.log(`Database connection closed for chatId: ${chatId}`);
    }
});

server.use(express.json()); 

server.post("/update-user-data", async (req, res) => {
    console.log("Received update-user-data request:", req.body);

    const { chatId, coins } = req.body;

    if (!chatId || !coins) {
        console.error('Missing required fields:', req.body);
        return res.status(400).send("Bad Request: Missing chatId or coins");
    }

    const client = new MongoClient(uri);

    try {
        console.log("Connecting to MongoDB...");
        await client.connect();
        console.log("Connected to MongoDB. Updating user data...");

        const db = client.db("myDatabase");
        const result = await db.collection("users").updateOne(
            { chatId: chatId },
            { $set: { coins: coins } }
        );

        if (result.matchedCount > 0) {
            console.log(`User ${chatId} updated successfully with coins: ${coins}`);
            res.send("User data updated successfully");
        } else {
            console.log(`User ${chatId} not found`);
            res.status(404).send("User not found");
        }
    } catch (err) {
        console.error('Error updating user data:', err);
        res.status(500).send("Server error");
    } finally {
        console.log("Closing MongoDB connection...");
        await client.close();
    }
});

server.listen(port, () => {
    console.log(`Server is running on port ${port}`);
});

My issue is that POST does not work. neither on my client, nor using POSTMAN which returns timeout. The only thing that works is CURL on my server. However GET works just fine. I have prompted GPT for hours. Thanks for any help!

This is the CURL that works if prompted in my server console

curl -X POST http://localhost:5000/update-user-data -H "Content-Type: application/json" -d '{"chatId": 396146507, "coins": 2200}'

it does change the data in my MongoDB correctly


Solution

  • It seems that json parser middleware changes the request so that body cannot be parsed when proxied (which is why GET works), see here: POST request body is not proxied to the servers

    So, change the order of middleware: move json parser middleware after proxy middleware:

    const app = express();
    
    // this has to come after proxy middleware
    
    //app.use(express.json());  // Ensure JSON request bodies are parsed
        
    app.use((req, res, next) => {
        if (req.url.startsWith('/get-user-data/')) {
            console.log(`Proxying GET request to motchi process: ${req.url}`);
            proxy.web(req, res, { target: 'http://localhost:5000' }, (error) => {