Commit 684a45fe authored by MARGERY David's avatar MARGERY David
Browse files

Compute absolute urls using X-Forwarded-Host

See bug #8536 for the context.

With this code, absolute urls of type :in (exposing how to reach g5k-api
resources) now only rely on the config file (base_uri_in) if no
X-Forwarded-Host, added by the request by proxies, is present.
parent 8d8325e0
......@@ -50,6 +50,7 @@ test: &test
<<: *defaults
base_uri_in: http://api-in.local
base_uri_out: http://api-out.local
from.config: http
reference_repository_path: spec/fixtures/reference-repository
notifications_uri: http://fake.api/sid/notifications
smtp_host: localhost
......
......@@ -65,9 +65,9 @@ module Grid5000
uri = "/" if uri.blank?
# abasu / dmargery - bug ref 7360 - for correct URI construction
if in_or_out == :out || relative_or_absolute == :absolute
root_uri=URI(base_uri(in_or_out))
if root_uri.path.blank?
root_path=''
root_uri=URI(base_uri(request, in_or_out))
if root_uri.path.blank?
root_path=''
else
root_path=root_uri.path+'/'
end # if root_uri.path.blank?
......@@ -79,20 +79,18 @@ module Grid5000
# FIXME: move Rails.config to Grid5000.config
def base_uri(in_or_out = :in)
Rails.my_config("base_uri_#{in_or_out}".to_sym)
end # def base_uri()
def tls_options_for(url, in_or_out = :in)
tls_options={}
[:cert_chain_file, :private_key_file, :verify_peer, :fail_if_no_peer_cert,
:cipher_list, :ecdh_curve, :dhparam, :ssl_version].each do |tls_param|
config_key=("uri_#{in_or_out.to_s}_"+tls_param.to_s).to_sym
if Rails.my_config(config_key)
tls_options[tls_param]=Rails.my_config(config_key)
def base_uri(request, in_or_out = :in)
if request.env.has_key?('HTTP_X_FORWARDED_HOST')
hosts=request.env['HTTP_X_FORWARDED_HOST'].split(',')
frontend=hosts[0]
if Rails.my_config(frontend.to_sym)
"#{Rails.my_config(frontend.to_sym)}://#{frontend}"
else
"https://#{frontend}"
end
else
Rails.my_config("base_uri_#{in_or_out}".to_sym)
end
tls_options
end
end
end
......
......@@ -15,80 +15,186 @@
require 'spec_helper'
describe Grid5000::Router do
before do
end
it "should take into account X-Api-Version header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sid/sites/rennes/jobs"
end
it "should take into account X-Api-Path-Prefix header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_PATH_PREFIX' => 'grid5000'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/grid5000/sites/rennes/jobs"
end
it "should take into account X-Api-Root-Path header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'proxies/grid5000'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/proxies/grid5000/sites/rennes/jobs"
end
it "should take into account X-Api-Mount-Path header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => 'sites/rennes'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/jobs"
end
it "should only substitute X-Api-Mount-Path header at the start of url" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => '/rennes'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sites/rennes/jobs"
end
it "should take into account both X-Api-Version and X-Api-Path-Prefix headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'grid5000'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sid/grid5000/sites/rennes/jobs"
end
describe "uri_to called with default parameters (:in and :relative)" do
it "should take into account X-Api-Version header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sid/sites/rennes/jobs"
end
it "Should properly combine X-API-[Mount-Path,Version,Path-Prefix] headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => '/sites/rennes/',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sid/g5k-api/jobs"
it "should take into account X-Api-Path-Prefix header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_PATH_PREFIX' => 'grid5000'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/grid5000/sites/rennes/jobs"
end
it "should take into account X-Api-Root-Path header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'proxies/grid5000'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/proxies/grid5000/sites/rennes/jobs"
end
it "should take into account X-Api-Mount-Path header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => 'sites/rennes'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/jobs"
end
it "should only substitute X-Api-Mount-Path header at the start of url" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => '/rennes'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sites/rennes/jobs"
end
it "should take into account both X-Api-Version and X-Api-Path-Prefix headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'grid5000'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sid/grid5000/sites/rennes/jobs"
end
it "Should properly combine X-API-[Mount-Path,Version,Path-Prefix] headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => '/sites/rennes/',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sid/g5k-api/jobs"
end
it "Should properly combine X-API-[Root-Path,Version,Path-Prefix] headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'proxies/grid5000',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/proxies/grid5000/sid/g5k-api/sites/rennes/jobs"
end
it "Should properly combine all X-API headers supported" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'sites/fr/grid5000',
'HTTP_X_API_MOUNT_PATH' => '/sites/',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sites/fr/grid5000/sid/g5k-api/rennes/jobs"
end
end
it "Should properly combine X-API-[Root-Path,Version,Path-Prefix] headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'proxies/grid5000',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/proxies/grid5000/sid/g5k-api/sites/rennes/jobs"
end
describe "uri_to called for absolute parameters (:in and :absolute)" do
#used for job creation, deletion and redirect to dashboard
before do
@server_url="http://api-in.local"
@proxy_header="proxy.public, proxy.local"
@proxy_url="https://proxy.public"
expect(Rails.my_config("base_uri_in".to_sym)).to eq @server_url
end
it "Should properly combine all X-API headers supported" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'sites/fr/grid5000',
'HTTP_X_API_MOUNT_PATH' => '/sites/',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api'
})
Grid5000::Router.uri_to(request, "/sites/rennes/jobs").should == "/sites/fr/grid5000/sid/g5k-api/rennes/jobs"
it "should take into account X-Api-Version header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/sid/sites/rennes/jobs"
end
it "should take into account X-Api-Path-Prefix header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_PATH_PREFIX' => 'grid5000',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/grid5000/sites/rennes/jobs"
end
it "should take into account X-Api-Root-Path header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'proxies/grid5000',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/proxies/grid5000/sites/rennes/jobs"
end
it "should take into account X-Api-Mount-Path header" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => 'sites/rennes',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/jobs"
end
it "should only substitute X-Api-Mount-Path header at the start of url" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => '/rennes',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/sites/rennes/jobs"
end
it "should take into account both X-Api-Version and X-Api-Path-Prefix headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'grid5000',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/sid/grid5000/sites/rennes/jobs"
end
it "Should properly combine X-API-[Mount-Path,Version,Path-Prefix] headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_MOUNT_PATH' => '/sites/rennes/',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/sid/g5k-api/jobs"
end
it "Should properly combine X-API-[Root-Path,Version,Path-Prefix] headers" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'proxies/grid5000',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/proxies/grid5000/sid/g5k-api/sites/rennes/jobs"
end
it "Should properly combine all X-API headers supported" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_ROOT_PATH' => 'sites/fr/grid5000',
'HTTP_X_API_MOUNT_PATH' => '/sites/',
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_API_PATH_PREFIX' => 'g5k-api',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url}/sites/fr/grid5000/sid/g5k-api/rennes/jobs"
end
it "Should allow override of protocol" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_FORWARDED_HOST' => @proxy_header
})
expect(Rails).to receive(:my_config).with(:'proxy.public').twice.and_return("http")
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "#{@proxy_url.gsub!('https','http')}/sid/sites/rennes/jobs"
end
it "Should allow override of protocol from config file" do
request = double(Rack::MockRequest, :env => {
'HTTP_X_API_VERSION' => 'sid',
'HTTP_X_FORWARDED_HOST' => "from.config, "+@proxy_header
})
expect(Rails.my_config(:'from.config')).to eq "http"
expect(Grid5000::Router.uri_to(request, "/sites/rennes/jobs", :in, :absolute)).to eq "http://from.config/sid/sites/rennes/jobs"
end
end
it "should take into account the parameters of the config file with empty path" do
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment