英文:
.htaccess server-side routing and node environment redirects
问题
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);
});
英文:
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);
});
答案1
得分: 1
你做错了,不应该使用301重定向。
我假设你是通过向后端发送HTTP请求来发送电子邮件,所以你需要将后端的所有路径设置为特定路径,如/api
。然后,你可以使用以下答案来解决你的问题:
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]
英文:
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]
答案2
得分: 0
问题已通过在我的 server.js
文件底部添加此“捕获所有”路由来解决,位于将请求发送到发送电子邮件的其他路由之后。
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '/path/to/index.html'));
});
这样做的话,它只会在之前的路由都不匹配请求时执行。
另外,不要忘记在顶部添加 path
的导入语句:
const path = require("path");
英文:
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 for path
at the top:
const path = require("path");
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论