Home > Back-end >  .htaccess server-side routing and node environment redirects
.htaccess server-side routing and node environment redirects

Time:01-13

I have a React webapp with a Node.js server, the .htaccess file of my website used to redirect the webpages requests to index.html this however meant that the emails being sent from the forms on the site were not being delivered since the requests had to be redirected to the Node Environment. This was fixed by redirecting the requests to the Node Environment instead of the index.html inside my .htaccess file, however, this means that my server-side routing now broke and I am now getting the Cannot GET /end-point error whenever I type in the URL with an end-point in the browser window or if I refresh the page.

old .htaccess:

RewriteBase /
RewriteRule ^index\.html$ - [L]
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

current .htaccess:

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Is there a fix without either breaking my server-side routing or email delivering?

Edit:

server.js:

const express = require("express");
const app = express();
require("dotenv").config({path: "../.env"});
const bodyParser = require("body-parser");
const cors = require("cors");
const nodemailer = require("nodemailer");
var sgTransport = require('nodemailer-sendgrid-transport');
const multer = require("multer");

app.use(express.urlencoded({extended: true}));
app.use(express.json());

app.use(cors());

const transport = nodemailer.createTransport(sgTransport({
  auth: {
    api_key: process.env.SG_API_KEY
  }
}));

app.post("/send_schools_form", cors(), async (req, res) => {
  let {
    school,
    address,
    name,
    phone,
    email,
    substitutes
  } = req.body;

  var substitutesList = substitutes.reduce(function(a, b) {
  return a   '</br><ul><li>Startdatum: '   b.date   '</li><li>Tid: '   b.time   '</li>    <li>Info: '   b.info   '</li></ul>';
}, '');

  await transport.sendMail({
    from: process.env.USER_SENDER,
    to: process.env.USER_RECEIVER,
    subject: `Vikarie begäran ${school}`,
    html: `
    <ul>
      <li>Skola: ${school}</li>
      <li>Adress: ${address}</li>
      <li>Kontaktperson: ${name}</li>
      <li>Telefon: ${phone}</li>
      <li>E-post: ${email}</li>
    </ul>
    <ul>${substitutesList}</ul>
    `
  }, (err) => {
    if (err) {
      console.log(err);
      res.status(400).send('Error');
    } else {
      res.status(200).send('Success');
    }
  })
});

const upload = multer({
  storage: multer.memoryStorage()
});

let middleware = [
  cors(),
  upload.fields([
    {name: "cvFile", maxCount: 1},
    {name: "otherFile", maxCount: 1}
  ])
];

app.post("/send_substitutes_form", middleware, async (req, res) => {
  let {
    firstName,
    lastName,
    email,
    phone,
    address,
    city,
    postalCode,
    availability
  } = req.body;

  await transport.sendMail({
    from: process.env.USER_SENDER,
    to: process.env.USER_RECEIVER,
    subject: `Arbetsansökan ${firstName} ${lastName}`,
    html: `
    <ul>
      <li>Namn: ${firstName} ${lastName}</li>
      <li>E-post: ${email}</li>
      <li>Telefon: ${phone}</li>
      <li>Adress: ${address}</li>
      <li>Ort: ${city}, ${postalCode}</li>
      <li>Tillgänglighet: ${availability} dagar per vecka</li>
    </ul>
    `,
    attachments: [{
      filename: req.files["cvFile"][0].originalname,
      content: req.files["cvFile"][0].buffer
    },
    {
      filename: req.files["otherFile"][0].originalname,
      content: req.files["otherFile"][0].buffer
    }]
  }, (err) => {
    if (err) {
      console.log(err);
      res.status(400).send('Error');
    } else {
      res.status(200).send('Success');
    }
  })
});

const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
  console.log("Server is listening on port "   PORT);
});

CodePudding user response:

You are doing it wrong, you should not redirect with 301.

I'm assuming you are sending an email by post an http request to your backend, so you need to set all your backend with specific path like /api. Then you could use this answers to solve your problem:

RewriteEngine on

RewriteCond %{REQUEST_URI} ^/api/
RewriteRule (.*) /api/public/index.php [L]

RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

Check this and this

CodePudding user response:

The issue was solved by adding this "catch-all" route near the bottom of my server.js file, after the other routes that post the requests to send the emails.

app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, '/path/to/index.html'));
});

This way, it will only be executed if none of the previous routes matches the request.

Also don't forget the import statement at the top:

const path = require("path");
  • Related