简体   繁体   English

在 Nginx 上运行的 NodeJS 应用程序中出现“net::ERR_ABORTED 404”错误

[英]"net::ERR_ABORTED 404" error in a NodeJS app running on Nginx

I have an SPA facing this error and I cannot seem to figure out why I am receiving it.我有一个 SPA 面临这个错误,我似乎无法弄清楚为什么我会收到它。

Bellow, my server.js贝娄,我的 server.js

// Load Node modules
var express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const ejs = require('ejs');
var falaUser = require("./routes/falaUser");

//Config files
process.env['NODE_CONFIG_DIR'] = __dirname + '/config/';
console.log("Usando "+process.env['NODE_CONFIG_DIR'] +" como diretório de configurações");
var config = require("config");

// Initialise Express
var app = express();

// Render static files
app.use(express.static('./public/'));
app.use(bodyParser.json());
app.use("/falauser", falaUser);

// Set the view engine to ejs
app.set('view engine', 'ejs');
var server = app.listen(config.get("port"), config.get("hostname"), function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log('Rodando bacana em https://' + host + ':' + port)
});

// Root Route
app.get('/strapiClient', function (req, res) {
    res.render('pages/index');
});

Here, relevant part of nginx.conf在这里,nginx.conf 的相关部分

upstream strapiClient {
    server botboutique.com.br:3847;
}

Here, relevant part of nginx/sites-enabled/00-default.ssl.conf这里, nginx/sites-enabled/00-default.ssl.conf 的相关部分

    # strapiClient
    location /strapiClient  {
        root   html;
        index  index.html index.htm index.ejs;
        proxy_read_timeout 120;
        proxy_pass http://strapiClient;

        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

Here, my HTML header partials in my ..views/partials/hearders.conf在这里,我的 ..views/partials/hearders.conf 中的 HTML 标头部分

<header>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>BOTIKE - Robôsitos que conversam com pessoas e negócios</title>
    <link rel="icon" href="images/cropped-favicon_botike-192x192.png" />
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@500;900&display=swap">
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@400;700;900&display=swap">

    <!-- Bootstrap -->
    <link type="text/css" rel="stylesheet" href="css/bootstrap-4.4.1.css">

    <!-- Animação dos balões da capa -->
    <link type="text/css" rel="stylesheet" href="css/animation-icoHum.css">
    <link type="text/css" rel="stylesheet" href="css/animation-icoBot.css">
    <link type="text/css" rel="stylesheet" href="css/animation-lettering.css">
    <link type="text/css" rel="stylesheet" href="css/style.css">
    <link type="text/css" rel="stylesheet" href="css/stilo.css">
    <link type="text/css" rel="stylesheet" href="slick-1.8.1/slick/slick.css">
    <link type="text/css" rel="stylesheet" href="slick-1.8.1/slick/slick-theme.css">

    <!-- Script principal -->
    <script type="text/javascript" src="js/scripto.js"></script>
</header>

My scripts.ejs in ..views/partials/partials:我在 ..views/partials/partials 中的 scripts.ejs:

<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script type="text/javascript" src="js/jquery-3.4.1.min.js "></script>

<!-- Include all compiled plugins (below), or include individual files as needed -->
<script type="text/javascript" src="js/popper.min.js "></script>
<script type="text/javascript" src="js/bootstrap-4.4.1.js "></script>
<script type="text/javascript" src="slick-1.8.1/slick/slick.min.js"></script>
<script type="text/javascript" src="js/script.js "></script>

That´s my files structure:那是我的文件结构:

在此处输入图像描述

The rendered page can acessed at botboutique.com.br/strapiClient呈现的页面可以在botboutique.com.br/strapiClient 访问

A weird thing: while Edge and Firefox shows in the console the expected URL (botboutique.com.br/strapiClient/some-directory/some-file), Goolge Chrome supress "strapiCLient" from the URL).一件奇怪的事情:虽然 Edge 和 Firefox 在控制台中显示了预期的 URL(botboutique.com.br/strapiClient/some-directory/some-file),但 Goolge Chrome 从 URL 中抑制了“strapiCLient”)。

A final thing: I'm facing a "Refused to apply style from '<URL>' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled."最后一件事:我面临"Refused to apply style from '<URL>' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled." but I think that I must to correct 404 error first before going into this...但我认为在进入这个之前我必须先纠正 404 错误......

My /etc/nginx/conf-available:我的 /etc/nginx/conf 可用:

add_header X-Frame-Options sameorigin;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection '1; mode=block';
add_header X-Download-Options noopen;
add_header X-Permitted-Cross-Domain-Policies none;
add_header Content-Security-Policy "default-src https: data: wss: 'unsafe-inline' 'unsafe-eval'";
add_header Referrer-Policy strict-origin;

When you serve a web app rather than some kind of API endpoint under an URI prefix, generally you should choose当您在 URI 前缀下提供 Web 应用程序而不是某种 API 端点时,通常您应该选择

location /prefix/ {
    ...
}

rather than而不是

location /prefix {
    ...
}

You may think there should no significant difference in those two;您可能认为这两者应该没有显着差异; however, the difference is more than significant - the opened page will have different browsing context in those two cases.但是,差异非常显着——在这两种情况下,打开的页面将具有不同的浏览上下文 When you open your page using /strapiClient URI, your browsing context is / and when you open your page using /strapiClient/ URI, your browsing context is /strapiClient/ .当您使用/strapiClient URI 打开页面时,您的浏览上下文是/ ,当您使用/strapiClient/ URI 打开页面时,您的浏览上下文是/strapiClient/ And it is the browsing context that determines how relative links will be processed - would be the script from the <script type="text/javascript" src="js/scripto.js"> tag requested as /js/scripto.js or as /strapiClient/js/scripto.js .决定如何处理相对链接的是浏览上下文 - 将是来自<script type="text/javascript" src="js/scripto.js">标记的脚本,请求为/js/scripto.js或作为/strapiClient/js/scripto.js I cannot check Edge or Firefox right now;我现在无法检查 Edge 或 Firefox; however, using Google Chrome your assets are being requested differently using different prefixes with and without trailing slash.但是,使用谷歌浏览器时,您的资产请求不同,使用不同的前缀(带和不带斜杠)。

Using the location /prefix/ { ... } style has the following advantages:使用location /prefix/ { ... }样式有以下优点:

  • you'd never face the situation when the other route starting with the same prefix, eg /prefixed will be handled with the wrong location;您永远不会遇到以相同前缀开头的另一条路线,例如/prefixed将使用错误的位置处理的情况;

  • all the assets referred using relative links will get correct /prefix/ automatically when being requested;所有使用相对链接引用的资产在被请求时都会自动获得正确的/prefix/

  • you can easily strip the /prefix from the proxied URI using the autoreplace proxy_pass directive feature when it it's declaration includes an URI part (the trailing slash here is an URI part):您可以使用 autoreplace proxy_pass指令功能轻松地从代理 URI 中去除/prefix ,因为它的声明包含 URI 部分(此处的尾部斜杠是 URI 部分):

     location /prefix/ { proxy_pass http://upstream/; }

    This behavior is described in the proxy_pass directive documentation : proxy_pass指令文档中描述了此行为:

    If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:如果proxy_pass指令是用一个 URI 指定的,那么当一个请求被传递到服务器时,与该位置匹配的规范化请求 URI 的部分将被指令中指定的 URI 替换:

     location /name/ { proxy_pass http://127.0.0.1/remote/; }
  • The redirection from /prefix to /prefix/ will be automatically issued by nginx itself in most cases;/prefix/prefix/的重定向在大多数情况下会由 nginx 自己自动发出; this behavior is described in the location directive documentation : location指令文档中描述了此行为:

    If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of proxy_pass , fastcgi_pass , uwsgi_pass , scgi_pass , memcached_pass , or grpc_pass , then the special processing is performed.如果位置由以斜杠字符结尾的前缀字符串定义,并且请求由proxy_passfastcgi_passuwsgi_passscgi_passmemcached_pass ​​ss 或grpc_pass处理,则执行特殊处理。 In response to a request with URI equal to this string, but without the trailing slash, a permanent redirect with the code 301 will be returned to the requested URI with the slash appended.为了响应 URI 等于此字符串但没有尾部斜杠的请求,将返回带有代码 301 的永久重定向到附加斜杠的请求 URI。

Unfortunately I don't know for sure how you should change your express.static middleware function.不幸的是,我不确定您应该如何更改您的express.static中间件功能。 An English documentation page suggests the following approach:英文文档页面建议采用以下方法:

app.use('/static', express.static(path.join(__dirname, 'public')))

Russian translation of the aforementioned documentation page suggests a different one:上述文档页面的俄语翻译提出了不同的建议:

app.use('/static', express.static(__dirname + '/public'));

Or maybe you should define your URI prefix directly:或者也许你应该直接定义你的 URI 前缀:

app.use('/static', express.static('/strapiClient/public'));

Nevertheless, I hope this answers some of your questions, at least partially, and gives you some starting point of where to start debugging your app and the express static module behavior.尽管如此,我希望这至少能部分回答您的一些问题,并为您提供一些起点,让您了解从哪里开始调试您的应用程序和表达静态模块行为。

As @Ivan Shatsky pointed, be sure about browser context: that's prety important to understand how relative links will be served.正如@Ivan Shatsky 指出的那样,请确保浏览器上下文:了解如何提供相关链接非常重要。 In my scenario, I put an extra slash at the end of location /strapiClient/ and it makes everything work.在我的场景中,我在location /strapiClient/末尾添加了一个额外的斜杠,它使一切正常。 So, etc/nginx/sites-enabled/00-default.ssl.conf was the only file that I edit to resolve the context and find the files correctly.因此, etc/nginx/sites-enabled/00-default.ssl.conf是我编辑以解析上下文并正确找到文件的唯一文件。

Unfortunatelly and for some reason that I didn't understand (yet) NodeJS refused to serve the pages using express.static at server.js .不幸的是,出于某种我不理解的原因,NodeJS 拒绝在server.js使用express.static提供页面。 And the solution that worked for me is quite verbose and seems like a "brute force" approach:对我有用的解决方案非常冗长,似乎是一种“蛮力”方法:

app.use('*/images', express.static(path.join(__dirname + '/public/images')));
app.use('*/js', express.static(path.join(__dirname + '/public/js')));
app.use('*/css', express.static(path.join(__dirname + '/public/css')));
app.use('*/slick-1.8.1', express.static(path.join(__dirname + '/public/slick-1.8.1')));

Despite I'm still struggling with how NodeJS is serving the pages , this question is solved.尽管我仍在为 NodeJS 如何为页面提供服务而苦苦挣扎,但这个问题已经解决了。 Thanks again @Ivan.再次感谢@Ivan。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM