почему я получаю 404 от post-запросов api к приложению node express с обратным прокси-сервером nginx

#node.js #api #express #nginx #post

#node.js #API #экспресс #nginx #Публикация

Вопрос:

Я следовал этому руководству, чтобы развернуть мое приложение node express на digital ocean droplet с использованием обратного прокси-сервера nginx: https://lengstorf.com/code/deploy-nodejs-ssl-digitalocean /

Приложение обслуживает статические веб-страницы и имеет только один post-запрос в API. Он отлично работает при локальном запуске, но когда код выполняется на сервере, отправляющем мою базовую форму, возвращается 404.

Я очень новичок в этом, это первый веб-сайт, который я пытался разместить. Я не смог найти в Интернете ничего, что помогло бы решить эту конкретную проблему, поэтому дайте мне знать, если я могу предоставить более подробную информацию. Любая помощь приветствуется.

Вот мой серверный код:

 //App.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const router = require('./routes/index');
const app = express();

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', router);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
    //res.render('error');

  res.json({
    message: err.message,
       error: err
  });
    console.error(err.message);

});

module.exports = app;
  

 //index.js
const emailListApi = require('./EmailList');
const usersApi = require('./users');
const express = require('express');
const router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('./../public/index.html', { title: 'mySite' });
});

router.use('/api/emailList', emailListApi);
router.use('/api/user', usersApi);



module.exports = router;
  

 //EmailList.js
const options = require ('./options');
const express = require('express');
const router = express.Router();

const fs = require( 'fs' );

router.post('/add', (req, res, next) => {
    const name = req.body.name;
    const email = req.body.email;
    if(!name || !email) {
        res.sendStatus(400);
        console.info('  Bad request - Request does not contain name or email');
    } else {
        const path = req.body.filePath ?
            options.assetsDir   req.body.filePath : options.emailList;
        if(!fs.existsSync(path)) {
            fs.writeFileSync(path);
        }
        const entry = 'n'   name   ' ('   email   ')';
        fs.appendFileSync(path, entry);
        console.info('  Added '   name   ' ('   email   ') '   ' to the distribution list');

        res.sendStatus(204);
    }
});

module.exports = router;
  

Here is the html for my form:

 <!--contact.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
<div>
    <main>
        <form name="subForm" id="subscriptionForm" method="POST" action="/api/emailList/add" autocomplete="off">
            <div>
                <h2>Subscribe for updates:</h2>
            </div>
            <div>
                <div>
                    <label for="email">Email Address:</label>
                    <input name="txtEmail" id="email" type="email">
                    <span>Please enter a valid email address.</span>
                </div>
                <div>
                    <label for="name">Name:</label>
                    <input name="txtName" id="name" type="text">
                </div>
            </div>
            <div>
                <button type="submit" name="subButt">Submit</button>
            </div>
        </form>

    </main>
</div>
<script>
    const form = document.getElementById("subscriptionForm");
    if (form.addEventListener) { // addEventListener for chrome
        form.addEventListener("submit", function (event) {
            event.preventDefault();
            const xh = new XMLHttpRequest();
            xh.onreadystatechange = function () {
                if (xh.readyState == 4 amp;amp; xh.status == 200) {
                    console.log("bitchin");
                }
            };
            xh.open("POST", "/api/emailList/add", true);
            xh.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
            xh.send(JSON.stringify({
                email: form.email.value,
                name: form.name.value
            }));
        });
    } else if (form.attachEvent) { // attachEvent for IE
        form.attachEvent('onsubmit', function (event) {
            event.preventDefault();
            const xh = new XMLHttpRequest();
            xh.onreadystatechange = function () {
                if (xh.readyState == 4 amp;amp; xh.status == 200) {
                    console.log("bitchin");
                }
            };
            xh.open("POST", "/api/emailList/add", true);
            xh.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
            xh.send(JSON.stringify({
                email: form.email.value,
                name: form.name.value
            }));
        });
    }
</script>
</body>
</html>
  

и вот мой файл конфигурации с поддержкой сайтов для nginx:

 # HTTP -- redirect all traffic to HTTPS
server{
    listen 80;
    listen [::]:80 default_server ipv6only=on;
    return 301 https://$host$request_uri;
}

server {
    #Enable HTTP/2
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name alphamated.com;

    # Use the Let's Encrypt certificates
    ssl_certificate /etc/letsencrypt/live/mySite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mySite.com/privkey.pem;

    #Include the SSL configuration from cipherli.st
    include snippets/ssl-params.conf;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:3000/;
        proxy_ssl_session_reuse on;
        proxy_set_header Host $http_host;
        proxy_cache_bypass $http_upgrade;
        proxy_redirect off;
    }
    location /api {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:3000/;
        proxy_ssl_session_reuse on;
        proxy_set_header Host $http_host;
        proxy_cache_bypass $http_upgrade;
        proxy_redirect off;
    }
}
  

Комментарии:

1. Привет, Аррон. Добро пожаловать в Stackoverflow. Вы вызываете свое приложение на порт 80 или 443. Я вижу очень разные конфигурации для двух портов в вашей конфигурации nginx.

2. Привет, Эстебан, спасибо за ответ. Весь мой трафик должен направляться через https с использованием 443. Я следовал некоторым шаблонам и руководствам для своей конфигурации, возможно, не полностью понимая их (ошибка новичка, лол), но я понимаю, что эти первые несколько строк должны перенаправлять любые http-запросы на https. Если я попытаюсь перейти на домашнюю страницу http: // alphamated.com он перенаправляет на https:// alphamated.com , и мой запрос post отображается как https:// alphamated.com/api/emailList/add , но возвращает 404