简体   繁体   English

为什么我在 nginx 下使用 Sinatra 时会出现 404 错误?

[英]Why am I getting 404 errors with Sinatra with Passenger under nginx?

I have a Sinatra-based app that runs fine locally.我有一个在本地运行良好的基于 Sinatra 的应用程序。

I moved it to a nginx-based server with Passenger and now all my links to files in my apps /public are returning 404 errors.我将它移到了基于 nginx 的服务器上,现在我的应用程序/public中的所有文件链接都返回 404 错误。 The primary app runs, is able to access the HAML templates in /view , which render correctly.主应用程序运行,能够访问/view中正确呈现的 HAML 模板。 The files exist and permissions are correct;文件存在且权限正确; I can open and edit them so I know they're there.我可以打开和编辑它们,所以我知道它们就在那里。

In my HAML templates I'm referring to the files that I can't access like this:在我的 HAML 模板中,我指的是我无法访问的文件,如下所示:

%script{ :src => 'js/jquery.js' }
%link{ "rel" => "stylesheet", "href" => "styles/input.css" }

My config.ru has gone through a lot mutations while I try to find the problem.当我试图找到问题时,我的config.ru经历了很多变化。 Currently I have:目前我有:

require 'sinatra'
require './peering_template.rb'

root_dir = File.dirname(__FILE__)

# disable :run
# set :root, root_dir
# set :views, File.join(File.dirname(__FILE__), 'views')
# set :environment, (ENV['RACK_ENV'] ? ENV['RACK_ENV'].to_sym : :development)

run Sinatra::Application 

The app exists in /home/apps/peering_template .该应用程序存在于/home/apps/peering_template中。

The web space is /home/webapps . web 空间是/home/webapps

There is a soft-link in /home/webapps like this: peering_template -> /home/apps/peering_template/public/ . /home/webapps中有一个软链接,如下所示: peering_template -> /home/apps/peering_template/public/

/home/webapps/
`-- peering_template -> /home/apps/peering_template/public/

The pertinent part of nginx.conf for this config is:此配置的 nginx.conf 的相关部分是:

server {
    listen      3000;
    server_name my_servers_name;
    root        /home/webapps;

    passenger_enabled  on;
    passenger_base_uri /peering_template;
}

Obviously, my server's name is different.显然,我的服务器名称不同。

The pertinent part from nginx' error.log is like this:来自 nginx 的 error.log 的相关部分是这样的:

"/home/webapps/js/jquery.js" failed (2: No such file or directory), request: "GET /js/jquery.js HTTP/1.1"

As near as I can tell this fits the directions for an " nginx and passenger configuration using sub-URIs ".据我所知,这符合“ nginx 和使用子URI 的乘客配置”的指示。 What am I missing?我错过了什么?


/home/apps/peering_template/
|-- config.ru
|-- lib
|   |-- bgp-config.rb
|   |-- ios-xr-config.rb
|   |-- ipv4_ipv6_grammar.rb
|   `-- ipv4_ipv6_grammar.treetop
|-- nginx.conf
|-- peering_template.rb
|-- public
|   |-- js
|   |   |-- jquery-1.6.min.js
|   |   |-- jquery-ui-1.8.12.custom.zip
|   |   |-- jquery.js -> jquery-1.6.min.js
|   |   `-- scripts.js
|   |-- peering_template_tool.htm
|   `-- styles
|       `-- input.css
|-- spreadsheets
|   |-- Peering Template-AMS-IX.xlsx
|   `-- Peering Template-IOS-XR-ASH1.xlsx
|-- tmp
|   `-- always_restart.txt
`-- views
    |-- index.haml
    `-- output.haml

I'm not sure if it matters but this is on a CentOS release 5.3 (Final) host, running nginx/1.0.0 and passenger (3.0.7) .我不确定这是否重要,但这是在CentOS release 5.3 (Final)主机上,运行nginx/1.0.0passenger (3.0.7)

In the original question I wrote:在最初的问题中,我写道:

I moved it to a nginx-based server with Passenger and now all my links to files in my apps /public are returning 404 errors.我将它移到了基于 nginx 的服务器上,现在我的应用程序 /public 中的所有文件链接都返回 404 错误。 The primary app runs, is able to access the HAML templates in /view, which render correctly.主应用程序运行,能够访问 /view 中正确呈现的 HAML 模板。 The files exist and permissions are correct;文件存在且权限正确; I can open and edit them so I know they're there.我可以打开和编辑它们,所以我知道它们就在那里。

That was my clue.那是我的线索。 On my fourth pass or so through the Passenger docs I ran into a section that talked about errors with /public assets:在我通过乘客文档的第四次左右时,我遇到了一个讨论/public资产错误的部分:

The second and highly recommended way is to always use Rails helper methods to output tags for static assets.第二种也是强烈推荐的方法是始终对 static 资产的 output 标记使用 Rails 辅助方法。 These helper methods automatically take care of prepending the base URI that you've deployed the application to.这些辅助方法会自动处理您已将应用程序部署到的基本 URI。 For images there is image_tag, for JavaScript there is javascript_include_tag and for CSS there is stylesheet_link_tag.对于图像,有 image_tag,对于 JavaScript,有 javascript_include_tag,对于 CSS,有 stylesheet_link_tag。 In the above example you would simply remove the HTML tag and replace it with inline Ruby like this:在上面的示例中,您只需删除 HTML 标记并将其替换为内联 Ruby ,如下所示:

So, that got me searching for similar helpers for Sinatra.所以,这让我为 Sinatra 寻找类似的助手。 I found in Sinatra's extensions page :我在Sinatra 的扩展页面中找到:

sinatra-url-for construct absolute paths and full URLs to actions in a Sinatra application sinatra-url-for 为Sinatra 应用程序中的操作构建绝对路径和完整 URL

sinatra-static-assets implements image_tag, stylesheet_link_tag, javascript_script_tag and link_tag helpers. sinatra-static-assets实现了 image_tag、stylesheet_link_tag、javascript_script_tag 和 link_tag 助手。 These helpers construct correct absolute paths for applications dispatched to sub URI.这些助手为分派到子 URI 的应用程序构造正确的绝对路径。

And that got me searching Sinatra's docs because it sparked a memory, and I relearned Sinatra's built-in "url" method:这让我搜索了 Sinatra 的文档,因为它引发了 memory,我重新学习了Sinatra 的内置“url”方法:

Generating URLs生成 URL

For generating URLs you should use the url helper method, for instance, in Haml:要生成 URL,您应该使用 url 辅助方法,例如在 Haml 中:

%a{:href => url('/foo')} foo %a{:href => url('/foo')} foo

It takes reverse proxies and Rack routers into account, if present.它考虑了反向代理和机架路由器(如果存在)。

This method is also aliased to to (see below for an example).此方法也别名为 to(参见下面的示例)。

By using the static asset methods, or Sinatra's own url helper it fixed the problem.通过使用 static 资产方法,或 Sinatra 自己的 url 助手,它解决了问题。

The root in your nginx config should be the public (or some other) directory, not the root of the entire rails application: nginx 配置中的根目录应该是公共(或其他)目录,而不是整个 rails 应用程序的根目录:

root        /home/webapps/public;

Now put all your static files inside that directory, and Passenger will be smart enough to resolve the config.ru Rack up file from the parent directory automatically, but serve the files from the public directory if they exist through nginx.现在将所有 static 文件放在该目录中,Passenger 将足够聪明地自动解析父目录中的config.ru Rack 文件,但如果公共目录中的文件通过 nginx 存在,则提供这些文件。

For what it's worth, as well, you shouldn't need anything but the require of your application ruby file, and and the Sinatra init method in your rack file.对于它的价值,除了你的应用程序 ruby 文件和机架文件中的 Sinatra init 方法之外,你不需要任何东西。 Here's one I use in another app:这是我在另一个应用程序中使用的:

require 'application'
run Sinatra::Application

One other little note, best practice to stick a / in front of any URLs that reference these static files to ensure they're reachable wherever the page URL ends up, eg.另一个小注意事项,最佳实践是在引用这些 static 文件的任何 URL 前面加上/ ,以确保在页面 URL 结束的任何地方都可以访问它们,例如。 ...:src => '/js/jquery.js'...

Edit:编辑:

I think there's a fundamental problem with the way your app is setup on the server.我认为您的应用在服务器上的设置方式存在根本问题。 In my mind, it should look something like this:在我看来,它应该看起来像这样:

/app
  whatever.rb
  /public
    ...

The nginx config should point to app/public as the root, and the public directory should not be a symlink. nginx 配置应该指向app/public作为根,并且public目录不应该是符号链接。

With all that in mind, perhaps the root should just be set directly to /home/apps/peering_template/public ?考虑到所有这些,也许根目录应该直接设置为/home/apps/peering_template/public

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

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