将 Elixir Phoenix 请求从根域重定向到 www

问题描述 投票:0回答:3

我们在 Heroku 上有一个 Phoenix 应用程序,其 DNS 位于 Route 53。我们按照此博客文章设置了正确的 http 到 https 重定向:
http://building.vts.com/blog/2015/11/02/route53-ssl-naked-domain-redirect/

一切正常,剩下的就是将根重定向到子域 www。

是否有推荐的方法以 Phoenix 方式进行设置?

redirect heroku elixir phoenix-framework
3个回答
8
投票

只需在应用程序端点顶部的重定向中plug即可。

lib/app/endpoint.ex

defmodule App.Endpoint do
  use Phoenix.Endpoint, otp_app: :app

  socket "/socket", App.UserSocket

  plug App.Plugs.WWWRedirect
  # ...
end

lib/app/plugs/www_redirect.ex

defmodule App.Plugs.WWWRedirect do
  import Plug.Conn

  def init(options) do
    options
  end

  def call(conn, _options) do
    if bare_domain?(conn.host) do
      conn
        |> Phoenix.Controller.redirect(external: www_url(conn))
        |> halt
    else
      conn # Since all plugs need to return a connection
    end
  end

  # Returns URL with www prepended for the given connection. Note this also
  # applies to hosts that already contain "www"
  defp www_url(conn) do
    "#{conn.scheme}://www.#{conn.host}"
  end

  # Returns whether the domain is bare (no www)
  defp bare_domain?(host) do
    !Regex.match?(~r/\Awww\..*\z/i, host)
  end
end

请注意,您需要重新启动服务器才能生效,因为

lib
中的任何内容都不会重新加载


2
投票

您还可以使用

plug_canonical_host
为您处理并确保您的 Elixir 应用程序只能通过其规范 URL 访问。


0
投票

为了完成 fny 的 anwser,我将添加带有查询字符串的完整请求路径:

defmodule App.Plugs.WWWRedirect do
  import Plug.Conn

  def init(options) do
    options
  end

  def call(conn, _options) do
    if bare_domain?(conn.host) do
      conn
      |> Phoenix.Controller.redirect(external: www_url(conn))
      |> halt
    else
      # Since all plugs need to return a connection
      conn
    end
  end

  # Returns URL with www prepended for the given connection. Note this also
  # applies to hosts that already contain "www"
  defp www_url(%{query_string: ""} = conn) do
    "#{conn.scheme}://www.#{conn.host}#{conn.request_path}"
  end

  defp www_url(conn) do
    "#{conn.scheme}://www.#{conn.host}#{conn.request_path}?#{conn.query_string}"
  end

  # Returns whether the domain is bare (no www)
  defp bare_domain?(host) do
    !Regex.match?(~r/\Awww\..*\z/i, host)
  end
end

© www.soinside.com 2019 - 2024. All rights reserved.