Search code examples
reactjssql-serverazureexpresscors

Getting error, WebSocket connection to 'wss://website.azurewebsites.net:8080/ws' failed: When making POST Request from React to Azure SQL server


I am having a problem with my azure web app (linux) while trying to add data into my sql database

Here are the errors im getting:

DataAdd.js:26 
POST https://website.azurewebsites.net:5000/add-data net::ERR_CONNECTION_TIMED_OUT
Error: TypeError: Failed to fetch
    at handleSubmit (DataAdd.js:26:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
    at invokeGuardedCallback (react-dom.development.js:4277:1)
    at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1)
    at executeDispatch (react-dom.development.js:9041:1)
    at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1)
    at processDispatchQueue (react-dom.development.js:9086:1)
    at dispatchEventsForPlugins (react-dom.development.js:9097:1)
    at react-dom.development.js:9288:1
WebSocketClient.js:13 WebSocket connection to 'wss://website.azurewebsites.net:8080/ws' failed:

Here is my DataAdd.js code:

import React, { useState } from 'react';
import './DataAdd.css';

const DataAdd = () => {
  const [formData, setFormData] = useState({
    description: '',
    Nimi: '',
    Syntymäaika: '',
    Rotu: '',
    Sukupuoli: '',
    Rekisterinumero: '',
    Omistaja: ''
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({
      ...formData,
      [name]: value
    });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const response = await fetch('https://website.azurewebsites.net:5000/add-data', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(formData)
      });
      if (response.ok) {
        alert('Data added successfully');
        setFormData({
          description: '',
          Nimi: '',
          Syntymäaika: '',
          Rotu: '',
          Sukupuoli: '',
          Rekisterinumero: '',
          Omistaja: ''
        });
      } else {
        alert('Error adding data');
      }
    } catch (error) {
      console.error('Error:', error);
      alert('Error adding data');
    }
  };

  return (
    <div>
      <h1>Add Data</h1>
      <form onSubmit={handleSubmit}>
        <div>
          <label>Description</label>
          <input type="text" name="description" value={formData.description} onChange={handleChange} required />
        </div>
        <div>
          <label>Nimi</label>
          <input type="text" name="Nimi" value={formData.Nimi} onChange={handleChange} required />
        </div>
        <div>
          <label>Syntymäaika</label>
          <input type="date" name="Syntymäaika" value={formData.Syntymäaika} onChange={handleChange} required />
        </div>
        <div>
          <label>Rotu</label>
          <input type="text" name="Rotu" value={formData.Rotu} onChange={handleChange} required />
        </div>
        <div>
          <label>Sukupuoli</label>
          <input type="text" name="Sukupuoli" value={formData.Sukupuoli} onChange={handleChange} required />
        </div>
        <div>
          <label>Rekisterinumero</label>
          <input type="text" name="Rekisterinumero" value={formData.Rekisterinumero} onChange={handleChange} required />
        </div>
        <div>
          <label>Omistaja</label>
          <input type="text" name="Omistaja" value={formData.Omistaja} onChange={handleChange} required />
        </div>
        <button type="submit">Add Data</button>
      </form>
    </div>
  );
};

export default DataAdd;

Here is my server.js code:

require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const sql = require('mssql');

const app = express();
const port = process.env.REACT_APP_AZURE_SERVER_PORT;

const config = {
    user: process.env.REACT_APP_AZURE_SQL_USER,
    password: process.env.REACT_APP_AZURE_SQL_PASSWORD,
    server: process.env.REACT_APP_AZURE_SQL_SERVER,
    port: parseInt(process.env.REACT_APP_AZURE_SQL_PORT, 10),
    database: process.env.REACT_APP_AZURE_SQL_DATABASE,
    authentication: {
        type: 'default'
    },
    options: {
        encrypt: true,
        requestTimeout: 60000,
        connectionTimeout: 30000
    }
};

// Add CORS middleware
app.use(cors({
    origin: 'https://website.azurewebsites.net', // Adjust based on your frontend URL
    methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
    preflightContinue: false,
    optionsSuccessStatus: 204
}));

// Add body parser middleware
app.use(express.json());

async function connectWithRetry() {
    let retries = 5;
    while (retries) {
        try {
            const pool = await sql.connect(config);
            return pool;
        } catch (err) {
            console.log(`Connection failed, retries left: ${retries - 1}`);
            console.error(err);
            retries -= 1;
            await new Promise(res => setTimeout(res, 5000)); // wait for 5 seconds before retrying
        }
    }
    throw new Error('Could not connect to the database after multiple attempts');
}

connectWithRetry().then(pool => {
    console.log("Connected to the database");

    app.post('/add-data', async (req, res) => {
        try {
            console.log('Received request:', req.body);
            const { description, Nimi, Syntymäaika, Rotu, Sukupuoli, Rekisterinumero, Omistaja } = req.body;

            console.log('Connecting to database...');
            const result = await pool.request()
                .input('description', sql.NVarChar, description)
                .input('Nimi', sql.NVarChar, Nimi)
                .input('Syntymäaika', sql.Date, Syntymäaika)
                .input('Rotu', sql.NVarChar, Rotu)
                .input('Sukupuoli', sql.NVarChar, Sukupuoli)
                .input('Rekisterinumero', sql.NVarChar, Rekisterinumero)
                .input('Omistaja', sql.NVarChar, Omistaja)
                .query(`
                    INSERT INTO dbo.hevoset (description, Nimi, Syntymäaika, Rotu, Sukupuoli, Rekisterinumero, Omistaja)
                    VALUES (@description, @Nimi, @Syntymäaika, @Rotu, @Sukupuoli, @Rekisterinumero, @Omistaja)
                `);

            console.log('Data added:', result);
            res.status(200).send('Data added successfully');
        } catch (err) {
            console.error('Error adding data:', err);
            res.status(500).send('Error adding data');
        }
    });

    app.listen(port, () => {
        console.log(`Server running on port ${port}`);
    });
}).catch(err => {
    console.error('Database connection failed: ', err.message);
});

What I have tried: Verified server is running: Server is running and logs indicate it is listening on the correct port.

Checked URL and port: Ensured that the URL and port in the React fetch call match the server's URL and port.

Configured CORS: Set CORS options to allow requests from the client URL.

Tested endpoint with curl/Postman: Direct requests to the server endpoint from curl/Postman work without issues.

Tested it on local, connection to the database works and so does adding data.

Added logging: Added logging to capture incoming requests and errors.

What I expect: I expect the POST request from my React application to successfully reach the SQL Server, allowing data to be added to the Azure SQL database.

Environment: Client: React web app hosted on Azure (Linux) Server: SQL server hosted on Azure Database: SQL database on Azure


Solution

  • I even tried to run your code but I get a WSS and CORS error, shown the same null data in adding. Then change your code as follows: the server-side logic stored in the backend code where we interact with db,api end points and process data.

    I configured CORS to allow requests from all urls to the backend as shown here:

    app.use(cors({
      origin: '*', 
      methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
      preflightContinue: false,
      optionsSuccessStatus: 204
    }));
    

    Change the INSERT query like this to avoid null:

    INSERT INTO hevoset (description, Nimi, Syntymäaika, Rotu, Sukupuoli, Rekisterinumero, Omistaja)
    VALUES (?, ?, ?, ?, ?, ?, ?)
    

    Backend:

    require('dotenv').config();
    const express = require('express');
    const cors = require('cors');
    const mysql = require('mysql2');
    const fs = require('fs');
    
    const app = express();
    const port = process.env.PORT || 8001;
    
    const config = {
      host: process.env.DB_HOST,
      user: process.env.DB_USER ,
      password:  process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      port: 3306,
      ssl: {
        ca: fs.readFileSync("DigiCertGlobalRootCA.crt.pem")
      }
    };
    
    const conn = mysql.createConnection(config);
    
    app.use(cors({
      origin: '*', 
      methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
      preflightContinue: false,
      optionsSuccessStatus: 204
    }));
    app.use(express.json());
    
    async function connectWithRetry() {
      let retries = 5;
      while (retries) {
        try {
          conn.connect(err => {
            if (err) {
              throw err;
            } else {
              console.log("Connected to the database");
            }
          });
          return;
        } catch (err) {
          console.log(`Connection failed, retries left: ${retries - 1}`);
          console.error(err);
          retries -= 1;
          await new Promise(res => setTimeout(res, 5000)); 
        }
      }
      throw new Error('Could not connect to the database after multiple attempts');
    }
    
    connectWithRetry().catch(err => {
      console.error('Database connection failed: ', err.message);
    });
    
    app.post('/add-data', (req, res) => {
      try {
        console.log('Received request:', req.body);
        const { description, Nimi, Syntymäaika, Rotu, Sukupuoli, Rekisterinumero, Omistaja } = req.body;
    
        const sql = `
          INSERT INTO hevoset (description, Nimi, Syntymäaika, Rotu, Sukupuoli, Rekisterinumero, Omistaja)
          VALUES (?, ?, ?, ?, ?, ?, ?)
        `;
    
        conn.query(sql, [description, Nimi, Syntymäaika, Rotu, Sukupuoli, Rekisterinumero, Omistaja], (err, results) => {
          if (err) {
            console.error('Error adding data:', err);
            res.status(500).send('Error adding data');
          } else {
            console.log('Data added:', results);
            res.status(200).send('Data added successfully');
          }
        });
      } catch (err) {
        console.error('Error adding data:', err);
        res.status(500).send('Error adding data');
      }
    });
    
    app.listen(port, () => {
      console.log(`Server running on port ${port}`);
    });
    

    The frontend code handles the user interface and user interactions for backend. I used axios to connect backend as shown here:

    const response = await axios.post('http://localhost:8001/add-data', formData);
    

    Frontend:

    import React, { useState } from 'react';
    import axios from "axios";
    import './DataAdd.css';
    
    const DataAdd = () => {
      const [formData, setFormData] = useState({
        description: '',
        Nimi: '',
        Syntymäaika: '',
        Rotu: '',
        Sukupuoli: '',
        Rekisterinumero: '',
        Omistaja: ''
      });
    
      const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData({
          ...formData,
          [name]: value
        });
      };
    
      const handleSubmit = async (e) => {
        e.preventDefault();
        try {
          const response = await axios.post('http://localhost:8001/add-data', formData);
          if (response.status === 200) {
            alert('Data added successfully');
            setFormData({
              description: '',
              Nimi: '',
              Syntymäaika: '',
              Rotu: '',
              Sukupuoli: '',
              Rekisterinumero: '',
              Omistaja: ''
            });
          } else {
            alert('Error adding data');
          }
        } catch (error) {
          console.error('Error:', error);
          alert('Error adding data');
        }
      };
    
      return (
        <div>
          <h1>Add Data</h1>
          <form onSubmit={handleSubmit}>
            <div>
              <label>Description</label>
              <input type="text" name="description" value={formData.description} onChange={handleChange} required />
            </div>
            <div>
              <label>Nimi</label>
              <input type="text" name="Nimi" value={formData.Nimi} onChange={handleChange} required />
            </div>
            <div>
              <label>Syntymäaika</label>
              <input type="date" name="Syntymäaika" value={formData.Syntymäaika} onChange={handleChange} required />
            </div>
            <div>
              <label>Rotu</label>
              <input type="text" name="Rotu" value={formData.Rotu} onChange={handleChange} required />
            </div>
            <div>
              <label>Sukupuoli</label>
              <input type="text" name="Sukupuoli" value={formData.Sukupuoli} onChange={handleChange} required />
            </div>
            <div>
              <label>Rekisterinumero</label>
              <input type="text" name="Rekisterinumero" value={formData.Rekisterinumero} onChange={handleChange} required />
            </div>
            <div>
              <label>Omistaja</label>
              <input type="text" name="Omistaja" value={formData.Omistaja} onChange={handleChange} required />
            </div>
            <button type="submit">Add Data</button>
          </form>
        </div>
      );
    };
    
    export default DataAdd;
    

    enter image description here

    enter image description here