Сообщение в блоге: http://livsey.org/blog/2012/02/23/using-rack-proxy-to-serve-multiple-rails-apps-from-the-same-domain-and-port/
Как использовать Rack:: Proxy в Rails для прокси-запросов для определенного пути к другому приложению
Ответ 1
Выяснил это.
Библиотека /proxy.rbrequire 'rack-proxy'
class Proxy < Rack::Proxy
def initialize(app)
@app = app
end
def rewrite_env(env)
# do magic in here
end
end
конфиг /application.rb
config.middleware.use "Proxy"
Ответ 2
FWIW, я также просто решил эту проблему. Некоторые могут найти полный код полезным, так как мне нужно больше, чем вы разместили:
# lib/proxy_to_other.rb
class ProxyToOther < Rack::Proxy
def initialize(app)
@app = app
end
def call(env)
original_host = env["HTTP_HOST"]
rewrite_env(env)
if env["HTTP_HOST"] != original_host
perform_request(env)
else
# just regular
@app.call(env)
end
end
def rewrite_env(env)
request = Rack::Request.new(env)
if request.path =~ %r{^/prefix|^/other_prefix}
# do nothing
else
env["HTTP_HOST"] = "localhost:3000"
end
env
end
end
также:
# config/application.rb
# ...snip ...
module MyApplication
class Application < Rails::Application
# Custom Rack middlewares
config.middleware.use "ProxyToOther" if ["development", "test"].include? Rails.env
#...snip....
Это предполагает, что ваше приложение, к которому вы хотите проксировать некоторые запросы, работает на порт 3001. Я полагаю, приложение, которое вы нажимаете, может быть запущено на любом порту. Это также предполагает, что вы хотите только проксировать в средах разработки и тестирования, потому что у вас будет "реальное" решение в производстве и постановке (например, nginx или loadbalancer, которые делают правильную вещь).
Ответ 3
Это небольшое изменение для решения steve, которое использует немного меньшее внутреннее понимание Rack::Proxy
:
require 'rack/proxy'
class MyProxy < Rack::Proxy
def initialize(app)
@app = app
end
def call(env)
# call super if we want to proxy, otherwise just handle regularly via call
(proxy?(env) && super) || @app.call(env)
end
def proxy?(env)
# do not alter env here, but return true if you want to proxy for this request.
return true
end
def rewrite_env(env)
# change the env here
env["HTTP_HOST"] = "some.other.host"
env
end
end
Ответ 4
Ниже приведен еще более простой код для прокси-сервера api, если вы хотите http://localhost:3000/api/users/1 (например), чтобы перейти в пространство имен api, определенное в routes.rb без использования прокси-серверной программы.
В процессе создания было бы что-то вроде http://api.sample.com/users/1.
Библиотека /proxy.rb
require 'rack-proxy'
class Proxy < Rack::Proxy
def perform_request(env)
request = Rack::Request.new(env)
if request.path =~ %r{^/api}
#do nothing
else
@app.call(env)
end
end
end
конфигурации /application.rb
config.middleware.use "Proxy"
конфигурации /routes.rb
namespace :api, defaults: { format: :json },
constraints: { subdomain: 'api' }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :users, :only => [:show, :create, :update, :destroy]
end
Библиотека /api _constraints.rb
class ApiConstraints
def initialize(options)
@version = options[:version]
@default = options[:default]
end
def matches?(req)
@default || req.headers['Accept'].include?("application/vnd.sample.v#{@version}")
end
end