Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir Phoenix global variable plug

I am trying to get the identifier of a website based on its domain, but after writing a plug for it, i am running into a problem wherein all the links in the system are returning the root url content.

lib/myapp/plugs/request_var.ex

defmodule Myapp.Plug.RequestVar do
  import Plug.Conn

  @doc false
  def init(default), do: default

  @doc false
  def call(conn, router) do
    host = conn.host
    if host == "ll.com" || host == "domain1.com" do
      slug = "domain1"
    else
      slug = "domain2"
    end

    conn |> put_private(:site_slug, slug)
  end
end

In lib/myapp/endpoint.ex

plug Myapp.Plug.RequestVar, Myapp.Router
plug Myapp.Router

Is anything wrong with this plug?

Edit: Fixed the "if" condition based on the responses.

like image 233
Pratik Khadloya Avatar asked Nov 23 '15 08:11

Pratik Khadloya


People also ask

What is plug in Phoenix Elixir?

Elixir is a functional language, so it's no surprise that one of the main building blocks of the request-response cycle is the humble Plug. A Plug will take connection struct (see Plug. Conn) and return a new struct of the same type.

What is Elixir plug?

In the Elixir world, Plug is the specification that enables different frameworks to talk to different web servers in the Erlang VM. If you are familiar with Ruby , Plug tries to solve the same problem that Rack does, just with a different approach.

What is Conn Elixir?

The "conn" object (abbreviation for connection) plays a critical role in the Phoenix framework. The conn is an Elixir struct, filled with information regarding a web request.


2 Answers

The url is generated from your endpoint.url and not the host for the Plug.Conn

From https://github.com/phoenixframework/phoenix/blob/8fe0538fd7be2adb05e2362b02fa8bd6bf3c6c46/lib/phoenix/router/helpers.ex#L13:

  def url(_router, %Conn{private: private}) do
    private.phoenix_endpoint.url
  end

  def url(_router, %Socket{endpoint: endpoint}) do
    endpoint.url
  end

  def url(_router, %URI{} = uri) do
    uri_to_string(uri)
  end

  def url(_router, endpoint) when is_atom(endpoint) do
    endpoint.url
  end

You can override this by using struct_url/0:

struct_url = update_in(Endpoint.struct_url.host, fn (_) -> "domain2" end)
some_url(struct_url, :index)

You can also define a second endpoint for your second domain. If your links are internal then you should consider using the _path functions instead of the _url functions. The _url helpers are generally used when the domain is required (such as emails.)

like image 156
Gazler Avatar answered Oct 22 '22 13:10

Gazler


You have an error in your if clause. It will always be true.

iex(1)> host = "l2.com"
"l2.com"
iex(2)> host == "ll.com" || "domain1.com"
"domain1.com"

For both valid and invalid domains.

iex(3)> host = "ll.com"                  
"ll.com"
iex(4)> host == "ll.com" || "domain1.com"
true

Test:

iex(6)> if host == "ll.com" || "domain1.com" do
...(6)>   IO.puts "if"
...(6)> end
if
:ok

You have to change your clause to if host == "ll.com" || host == "domain1.com" do. But. It is not idiomatic to use this kind of clauses. It is generally better to use pattern-matching.

like image 41
sobolevn Avatar answered Oct 22 '22 14:10

sobolevn