【问题标题】:Rails app GET routes not working in production modeRails 应用程序 GET 路线在生产模式下不起作用
【发布时间】:2018-12-14 06:23:59
【问题描述】:

我继承了一个 Rails 应用程序,该应用程序在生产模式下运行时功能不完整。对服务器的 GET 请求导致找不到路由匹配错误;但是,当服务器在开发模式下运行时,所有路由都将正常工作,并给出预期的 200 状态。

查看代码会发现,除了成功的 URL 请求中使用的域之外,应用程序还需要一个带前缀的子域。

class ApplicationContext
 def initialize(subdomain, host_with_port)
  if subdomain.present?
  case subdomain
  when Rails.application.config.workninja.admin_subdomain
    @environment = :admin
  when Rails.application.config.workninja.mobile_subdomain
    @environment = :mobile
  else
    @environment = :customer
  end
else
  raise 'Could not initialize ApplicationContext without subdomain'
end

@url_options = {subdomain: subdomain, host: host_with_port}

setup_method = "setup_#{@environment.to_s}_environment".to_sym
 if respond_to?(setup_method, true)
  send(setup_method, subdomain, host_with_port)
 else
   raise 'Unknown context environment'
 end
end

attr_reader :environment
attr_reader :url_options
attr_reader :agency

def self.current
 Thread.current['workninja:tenant_context']
end

def admin?
 @environment == :admin
end

def mobile?
 @environment == :mobile
end

def customer?
 @environment == :customer
end

 def ui_url_for(path, subdomain = url_options[:subdomain])
   base = "#{Rails.application.config.workninja.https ? 'https' : 
  'http'}://#{subdomain}.#{Rails.application.config.workninja.domain}"
 if Rails.application.config.workninja.html5mode
   puts URI.join(base, path).to_s
 else
   puts URI.join(base, "/#/#{path}".gsub(/\/+/, '/')).to_s
 end

end

应用程序提供的原始前端根据服务器启动的环境构造请求的 URL。

{
 "environment": "development",
 "url": "http://admin.workninja.local:3000"
}

{
 "environment": "production",
 "url": "/api"
}

对我来说,生产 URL 没有意义,因为它所做的只是将“/api”附加到前端托管的根域。我只能假设它只是一个占位符,一旦它在实时环境中运行,就需要用 Rails 服务器托管的域名替换。 “/api”路径并未在应用程序的整个功能开发版本中使用,这让我进一步假设它是一个占位符。

使用上述内容作为指导,我将“/api”替换为“http://admin.workninja.com.au”。在活动域上托管应用程序后,我通过运行确认它正在工作:

curl http://admin.workninja.com.com.au/auth -X POST 

这给了我一个关于未提供凭据的预期错误,但它表明服务器实际上正在接收某些内容。如果您还没有意识到 Rails 服务器在生产模式下启动时会响应 POST 请求,但仍然不会响应 GET。

这就是我对问题的理解崩溃的地方。如果

http://admin.workninja.local:3000/roles

在开发环境中工作(“/roles 是应用程序路由之一”)为什么不工作

http://admin.workninja.com.au/roles 

也在生产环境中工作?你能从这个事实中假设 ruby​​ 代码库中的某些东西没有损坏吗?

以下是一些与在生产环境中配置 rails 应用程序相关的文件。

/config/deploy/production.rb

set :branch, 'master'

server 'ec2-54-66-230-174.ap-southeast-2.compute.amazonaws.com', user: 'ubuntu', roles: %w{app web db worker}

/config/environments/production.rb

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # Code is not reloaded between requests.
  config.cache_classes = true

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both threaded web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.


  # This needs to be set to true in order for rails to launch in a production environment
  config.eager_load = false

  # Full error reports are disabled and caching is turned on.
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true

  # Enable Rack::Cache to put a simple HTTP cache in front of your application
  # Add `rack-cache` to your Gemfile before enabling this.
  # For large-scale production use, consider using a caching reverse proxy like
  # NGINX, varnish or squid.
  # config.action_dispatch.rack_cache = true

  # Disable serving static files from the `/public` folder by default since
  # Apache or NGINX already handles this.
  config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?


  # Specifies the header that your server uses for sending files.
  # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX

  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  # config.force_ssl = true

  # Use the lowest log level to ensure availability of diagnostic information
  # when problems arise.
  config.log_level = :warn

  # Prepend all log lines with the following tags.
  # config.log_tags = [ :subdomain, :uuid ]

  # Use a different logger for distributed setups.
  # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)

  # Use a different cache store in production.
  # config.cache_store = :mem_cache_store

  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
  # config.action_controller.asset_host = 'http://assets.example.com'

  # Ignore bad email addresses and do not raise email delivery errors.
  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
  # config.action_mailer.raise_delivery_errors = false

  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  # the I18n.default_locale when a translation cannot be found).
  config.i18n.fallbacks = true

  # Send deprecation notices to registered listeners.
  config.active_support.deprecation = :notify

  # Use default logging formatter so that PID and timestamp are not suppressed.
  config.log_formatter = ::Logger::Formatter.new

  # Do not dump schema after migrations.
  config.active_record.dump_schema_after_migration = false

  # Application hostname
  config.surgeforce.domain = 'surgeforce.com.au'
  config.surgeforce.https = false
  config.surgeforce.html5mode = true

end

/config/puma.rb

threads 1, 6
workers Integer(ENV['PUMA_WORKERS'] || 3)

on_worker_boot do
  require "active_record"
  cwd = File.dirname(__FILE__)+"/.."
  ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  ActiveRecord::Base.establish_connection(ENV["DATABASE_URL"] || YAML.load_file("#{cwd}/config/database.yml")[ENV["RAILS_ENV"]])
end

如果您认为应用程序代码的任何其他部分对调查至关重要,请告诉我,我会将其包括在内。

【问题讨论】:

  • 也许是生产中的自定义服务器配置,带有 url 重写,还是什么?它是您真实的生产环境,还是本地环境?应用程序本身中是否有可能仅在生产中有效的 Web 服务器配置?
  • 开发 URL 是一个包含协议、主机名和路径的全功能 URL。而生产 URL 只是一个路径。这是故意的吗?
  • @BradWerth 该环境是托管在 AWS 上的真正生产环境。我已经包含了一些与应用程序的生产部署相关的配置文件,但是我看不到与 URL 重写相关的任何内容,这会是什么样子?
  • @spickermann 抱歉,这只是一个错字,上面对生产 URL 的描述现在正确反映了它是一个功能齐全的 URL

标签: ruby-on-rails ruby curl get routes


【解决方案1】:

问题是Rails 的subdomain 方法非常简单,对com.au 域的结构一无所知。对于您在生产中使用的"admin.workninja.com.au"subdomain 方法将返回"admin.workninja"。来自文档:

将所有 \subdomains 作为字符串返回,因此 "dev.www" 将是 返回"dev.www.rubyonrails.org"。你可以指定一个不同的tld_length,比如2来捕捉"www"而不是“www.rubyonrails.co.uk”中的"www.rubyonrails"

而且 - 在不知道您的配置的情况下,– "admin.workninja" 很可能不再匹配您的 config.workninja.admin_subdomain 配置。

解决方案是在生产时configure a tld length of 2。只需将以下内容添加到 config/environments/production.rb 的配置块中:

config.action_dispatch.tld_length = 2 # Defaults to 1

【讨论】:

  • 非常感谢,这就是解决方案。
猜你喜欢
  • 2013-02-16
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多