Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove hard-coded base host_parts.length of 2 and add support for site subdomains #16

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Divergence::Application.configure do |config|
config.app_path = "/path/to/app_root"
config.cache_path = "/path/to/cache_root"

config.incoming_base_uri = 'example.com'

config.forward_host = 'localhost'
config.forward_port = 80

Expand Down
15 changes: 14 additions & 1 deletion generators/files/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,24 @@
# have it's own Passenger instance, so don't get too carried away.
# config.cache_num = 5

# Incoming base domain for requests, which will have a
# branch name prepended to it
config.incoming_base_uri = 'example.com'

# Where should we proxy this request to? Normally you can leave
# the host as 'localhost', but if you are using virtual hosts in
# your web server setup, you may need to be more specific. You
# will probably want Divergence to take over port 80 as well,
# so update your web application to run on a different port.
config.forward_host = 'localhost'
config.forward_port = 80
end

# If your site code is used for more than one virtual host, with
# one being a subdomain of the other (e.g. example.com and
# api.example.com) and both under the same git repository, you can supply
# the additional domains in the config.site_subdomains array.
# Note: if you use a config.forward_host value of 'localhost', then
# Divergence will make the request to api.localhost, so you probably
# want to use a different forward_host.
# config.site_subdomains = ['api']
end
11 changes: 10 additions & 1 deletion lib/divergence/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ class Configuration
attr_accessor :app_path, :git_path, :cache_path
attr_accessor :cache_num
attr_accessor :forward_host, :forward_port
attr_accessor :site_subdomains
attr_reader :incoming_base_uri_length

def initialize
@git_path = nil
Expand All @@ -13,13 +15,20 @@ def initialize

@cache_num = 5

@incoming_base_uri_length = 2
@forward_host = 'localhost'
@forward_port = 80
@site_subdomains = []

@callback_store = {}
@helpers = Divergence::Helpers.new(self)
end

def incoming_base_uri=(incoming_base_uri)
@incoming_base_uri = incoming_base_uri
@incoming_base_uri_length = @incoming_base_uri.split(".").length
end

def ok?
[:git_path, :app_path, :cache_path].each do |path|
if instance_variable_get("@#{path}").nil?
Expand Down Expand Up @@ -73,4 +82,4 @@ def each(&block)
end
end
end
end
end
37 changes: 16 additions & 21 deletions lib/divergence/request_parser.rb
Original file line number Diff line number Diff line change
@@ -1,44 +1,39 @@
module Divergence
class RequestParser
def initialize(env)

attr_accessor :called_site_subdomain

def initialize(env, config)
@req = Rack::Request.new(env)
@config = config

@host_parts = @req.host.split(".")
@called_site_subdomain = nil
end

def raw
@req
end

def is_webhook?
subdomain == "divergence" and
@host_parts[0] == "divergence" and
@req.env['PATH_INFO'] == "/update" and
@req.post?
end

def host_parts
@req.host.split(".")
end

def has_subdomain?
host_parts.length > 2
end

def subdomain
if has_subdomain?
host_parts.shift
else
nil
end
@host_parts.length > @config.incoming_base_uri_length
end

def branch
if has_subdomain?
branch = subdomain
branch = @host_parts[0]

if branch['-']
@git.discover(branch)
else
branch
if @config.site_subdomains.include?(branch)
@called_site_subdomain = branch
branch = @host_parts[1]
end
branch
else
nil
end
Expand All @@ -48,4 +43,4 @@ def method_missing(meth, *args, &block)
raw.send(meth, *args)
end
end
end
end
16 changes: 12 additions & 4 deletions lib/divergence/respond.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ class Application < Rack::Proxy
# The main entry point for the application. This is called
# by Rack.
def call(env)
@req = RequestParser.new(env)
@req = RequestParser.new(env, @@config)

# First, lets find out what subdomain/git branch
# we're dealing with (if any).
Expand All @@ -21,7 +21,7 @@ def call(env)
# Lets get down to business.
begin
# Get the proper branch name using a touch of magic
branch = @git.discover(@req.subdomain)
branch = @git.discover(@req.branch)

# Prepare the branch and cache if needed
path = prepare(branch)
Expand Down Expand Up @@ -62,7 +62,15 @@ def proxy(env)
# Sets the forwarding host for the request. This is where
# the proxy comes in.
def fix_environment!(env)
env["HTTP_HOST"] = "#{config.forward_host}:#{config.forward_port}"
if @req.called_site_subdomain
request_domain = "#{@req.called_site_subdomain}.#{config.forward_host}:#{config.forward_port}"
else
request_domain = "#{config.forward_host}:#{config.forward_port}"
end
env["HTTP_HOST"] = request_domain
# Tell Rack::Proxy to use request_domain for the backend request. This is
# needed in case HTTP_X_FORWARDED_HOST is supplied by another proxy
Rack::Proxy.instance_method(:initialize).bind(self).call(:backend => "http://#{request_domain}")
end

def error!(branch)
Expand All @@ -77,4 +85,4 @@ def error!(branch)
[404, {"Content-Type" => "text/html"}, [contents]]
end
end
end
end