Định tuyến đường ray để xử lý nhiều miền trên một ứng dụng


90

Tôi không thể tìm ra giải pháp khả thi cho vấn đề này, mặc dù có một số câu hỏi tương tự ở đây và ở những nơi khác. Có vẻ như câu hỏi này chưa được trả lời cho Rails 3, vì vậy đây là:

Tôi có một ứng dụng hiện cho phép người dùng tạo miền phụ của riêng họ chứa phiên bản ứng dụng của họ. Trong khi trong Rails 2, bạn được phục vụ tốt nhất bằng cách sử dụng gem-fu miền phụ, trong phiên bản 3, nó đơn giản hơn đáng kể, theo Railscast - http://railscasts.com/episodes/221-subdomains-in-rails-3 .

Đó là công cụ tốt, nhưng tôi cũng muốn cung cấp tùy chọn để người dùng liên kết tên miền của riêng họ với tài khoản của họ. Vì vậy, mặc dù họ có thể có http://userx.mydomain.com , tôi cũng muốn họ chọn liên kết với http://userx.com .

Tôi đã tìm thấy một vài tài liệu tham khảo để thực hiện việc này trong Rails 2, nhưng những kỹ thuật đó dường như không hoạt động nữa (đặc biệt là kỹ thuật này: https://feefirors.com/blog/hosting-multiple-domains-from-a-single-rails -app / ).

Có ai có thể giới thiệu cách sử dụng các tuyến để chấp nhận một miền tùy ý và chuyển miền đó cho bộ điều khiển để tôi có thể hiển thị nội dung thích hợp không?

Cập nhật : Bây giờ tôi đã có hầu hết câu trả lời, nhờ phản hồi kịp thời của Leonid và một cái nhìn mới về mã. Cuối cùng, nó yêu cầu bổ sung vào mã Tên miền phụ hiện có mà tôi đang sử dụng (từ giải pháp Railscast) và sau đó thêm một chút vào route.rb. Tôi vẫn chưa đến đó nhưng tôi muốn đăng những gì tôi có cho đến nay.

Trong lib / subdomain.rb:

class Subdomain
  def self.matches?(request)
    request.subdomain.present? && request.subdomain != "www"
  end
end

class Domain
  def self.matches?(request)
    request.domain.present? && request.domain != "mydomain.com"
  end
end

Tôi đã thêm lớp thứ hai để bắt chước lớp thứ nhất, được biết là đang hoạt động. Tôi chỉ cần thêm một điều kiện đảm bảo rằng miền đến không phải là miền mà tôi đang lưu trữ trang web chính.

Lớp này được sử dụng trong các route.rb:

require 'subdomain'
constraints(Domain) do
  match '/' => 'blogs#show'
end

constraints(Subdomain) do
  match '/' => 'blogs#show'
end

Ở đây, tôi đang thêm mã miền phụ hiện có (một lần nữa, nó hoạt động tốt) với một đoạn thơ để kiểm tra Tên miền. Nếu máy chủ này phản hồi với miền đó và nó không phải là miền mà trang web chính hoạt động, hãy chuyển tiếp đến bộ điều khiển được chỉ định.

Và trong khi điều đó dường như đang hoạt động, tôi vẫn chưa hoàn toàn thấy mọi thứ hoạt động, nhưng tôi nghĩ vấn đề cụ thể này đã được giải quyết.


1
Cảm ơn rất nhiều vì chỉnh sửa của bạn, Aaron. Tôi đang đối phó với tình huống tương tự ngay bây giờ. Như một câu hỏi tiếp theo, làm cách nào để máy chủ của bạn chấp nhận bất kỳ miền nào đang được chuyển tiếp đến nó? Tôi cho rằng đó sẽ là một cài đặt trong tệp .conf, nhưng tôi không chắc chắn về điều gì. Bất kỳ trợ giúp sẽ được đánh giá cao!
deadwards

Aaron, tôi đi cùng bạn. Tôi muốn làm điều tương tự. Nhưng tôi không muốn mã hóa miền. Tôi muốn tất cả được thực hiện theo chương trình mà không có tệp vùng và máy chủ web khởi động lại.
Michael K Madison

1
Michael, bạn cần lật lại vấn đề. Khai báo rõ ràng & mã hóa các tuyến đường dành riêng cho ứng dụng của bạn (ví dụ: đăng ký) với ràng buộc máy chủ lưu trữ hoặc miền phụ, sau đó coi các tuyến đường chính của bạn là "miền hoặc miền phụ bất kỳ". Sau đó, bộ điều khiển của bạn có trách nhiệm tra cứu tên miền hoặc tên miền phụ hiện tại và ánh xạ nó đến đúng khách hàng.
Justin French

Câu trả lời:


95

Nó thực sự đơn giản hơn trong Rails 3, theo http://guides.rubyonrails.org/routing.html#advanced-constraints :

1) xác định một lớp ràng buộc tùy chỉnh trong lib/domain_constraint.rb:

class DomainConstraint
  def initialize(domain)
    @domains = [domain].flatten
  end

  def matches?(request)
    @domains.include? request.domain
  end
end

2) sử dụng lớp trong các tuyến của bạn với cú pháp khối mới

constraints DomainConstraint.new('mydomain.com') do
  root :to => 'mydomain#index'
end

root :to => 'main#index'

hoặc cú pháp tùy chọn kiểu cũ

root :to => 'mydomain#index', :constraints => DomainConstraint.new('mydomain.com')

6
Câu trả lời này có vẻ đơn giản hơn nhiều đối với tôi.
Jared

7
Đây là một giải pháp tuyệt vời. Nó hoạt động như thế nào với môi trường phát triển?
siêu thường

2
@superluminary nó hoạt động hoàn toàn tốt nếu bạn thiết lập các miền cục bộ để phát triển (ví dụ: qua /etc/hosts).
Leonid Shevtsov

7
Lưu ý: nếu bạn sử dụng Pow cục bộ và có mydomain.com.dev, thì request.domaintrả về .com.dev. Thay đổi request.domainthành request.hostvà nó hoạt động hoàn hảo.
Eric Muyser

2
Tôi đã phát hiện ra rằng tôi phải tạo ra các tuyến đường giấu tên cho điều này để làm việc, nếu không tôi nhận được Invalid route name, already in use: 'root'lỗi ... Để làm điều này, tôi đã thay đổi các tuyến đường đếnroot :to => 'mydomain#index', as: nil
Chỉ cần Lucky Really

5

Trong Rails 5, bạn chỉ cần thực hiện việc này trong các tuyến của mình:

constraints subdomain: 'blogs' do
  match '/' => 'blogs#show'
end
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.