How to get the current URL?

I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just finding my way around the docs eg not even sure where to find info on conn opt.

Thanks

1 Like

Here you go:

https://hexdocs.pm/plug/Plug.Conn.html

2 Likes

Oh thanks,

I meant to say, as an aside, I couldn’t find info for the singular ‘opt’, but now relooking at it, it’s a common abbreviation. Gah I’m a noob.

But on the topic - I’ve looked through plug.conn already and wondered if I should use request_path as this is all I need (there is no query path in what I’m trying to get, and as it’s my app, there’s no need to check the host) - and how would I use it?

What would you like to do with it?

In a controller it’s accessible via conn.request_path. In a template it’s accessible via @conn.request_path.

Here’s a good example:

It adds class="active" to links that point to the current page.

3 Likes

Thanks,

I’m trying to customise Coherence’s links (the buttons you helped me with recently) in the navbar I’ve made so that on the home page of the app, when a user isn’t signed in, the register ("Need an Account) and signin links are visible - as they current are - but when clicking on the register button that takes the user to /registrations/new - just the signin button is displayed, and when they click the signin button and go to that page - just the register button is displayed.

Here’s the code that does the links (buttons):

if Coherence.logged_in?(conn) do
      current_user = Coherence.current_user(conn)
      [
        content_tag(list_tag, current_user.name),
        content_tag(list_tag,
          button(signout, to: coherence_path(@helpers, :session_path, conn, :delete, current_user), method: :delete, class: signout_class))
      ]
    else
      signin_link = content_tag(list_tag, link(signin, to: coherence_path(@helpers, :session_path, conn, :new), class: button_class), class: list_class)
      if Config.has_option(:registerable) && register do
        [content_tag(list_tag, link(register, to: coherence_path(@helpers, :registration_path, conn, :new), class: button_class), class: list_class), signin_link]
      else
        signin_link
      end
  end

I’m confused by the && register do of if Config.has_option(:registerable) && register do
and have tried to make another if/else so that there’s one for the registration_path and one for the session_path, but I can’t check/match the url correctly so the right one is chosen and button I want displayed shown.

This is the kind of code I’ve tried:

if Config.has_option(:registerable) && conn.request_path === :session_path do

I’ve tried a lot of other approaches, so would love to know how to properly do this as it should help clear some of thinking about how to use elixir and phoenix. Thanks

btw. the main question still stays unanswered - as there’s no single method which returns full request uri, you need to build it by yourself by using scheme/host/port/request_path/query_params fields - which is kinda weird

1 Like

I have opened up an issue in Phoenix. We could certainly introduce current_path and current_url.

1 Like

shouldn’t request_url live in Plug.Conn?

request_url is not the same as current_url. For example, if your server is behind a proxy, the request_url is rather “http://132.54.51.90:8000/foo/bar”, where the host is the internal IP address, and nobody wants that. :slight_smile: So I think something that understands your application configuration is preferrable.

1 Like

hmm, strange because when we run it behind ELB, conn.host is the actual domain name and not elixir machine ip, so why request_url should work otherwise?

Proxies usually set the Host header when they send a request to the backend. Nginx usually has a line proxy_set_header Host $http_host; which sets the right host header for the forwarded requests. Having a request_url in the plug may help other frameworks too :slight_smile:

1 Like

Sorry to ask this, as it’s great to see discussion about how this can be done in the future or different architectural/server scenarios, but how can I go about doing this now just developing in a locally created app and in the context of the code I’ve posted? I’m hoping your thoughts will clarify how I can re-use/modify it for similar situations and how to write elixir, until a better approach is created in phoenix.

thanks

The simplest way is to get the normalized path in your view:

"/" <> Enum.join(@conn.path_info, "/")

The simplest way is to get the request path, which is the path as typed in the browser, not normalized (for example, it may have double slashes - and I am not talking about the guitarist) in your view:

@conn.request_path

And if you want the url from those, you can use the url/1 function:

url(@conn, "/" <> Enum.join(@conn.path_info, "/"))
url(@conn, @conn.request_path)
3 Likes

Thanks, I’ve got it working now!

If anyone is trying to do this you have two solutions:

  1. In controller use current_url(conn)
  2. in views because Mockapp.Web.Router.Helpers is imported in YourApp.ex you ca do this in your template:
    <%= url(@conn) %>
3 Likes

Why not having current_path and current_url directly in Plug?

1 Like

But in case I need URL params keys within request url, there is no any way to get it.
For example:
I need path in this way “/teams/:team_id/user_teams/:id”, but conn.request_path and current_path gives like this “/teams/2/user_teams/1”

See Phoenix.Router — Phoenix v1.6.10

2 Likes

Thank You @LostKobrakai, wondering why I couldn’t see this method.