niccolox

niccolox

Can I route on cookies using Routex?

hi, thanks for this

can I Route on cookies, similar to this question: Is it possible to modify Router matches based on cookies like in Varnish? - #3 by dimitarvp

I want to be able to present a static cached page using http_cache | Hex if no cookies and if there are cookies I want to route to a non cached cookied page


in Varnish you can do:

sub vcl_hash {
  if (req.http.cookie ~ "wordpress_logged_in_") {
    hash_data("wordpress_logged_in");
  }
  # the builtin.vcl will take care of also varying cache on Host/IP and URL 
}

or better

import cookie;
import directors;
import std;
import kvstore;

sub vcl_init {
    kvstore.init(0, 1000);
}

sub vcl_backend_response {
    set beresp.http.x-tmp = regsub(header.get(beresp.http.set-cookie,"JSESSIONID=", " *;.*", "");
    if (beresp.http.x-tmp != "") {
        kvstore.set(0, cookie.get("id"), beresp.backend, 15m);
    }
    unset beresp.http.x-tmp;
}

sub vcl_recv {
    cookie.parse(req.http.cookie);
    set req.http.server = kvstore.get(0, cookie.get("id"), "none");

    if (req.http.server == "s1") {
        set req.backend_hint = s1;
    } else if (req.http.server == "s2") {
        set req.backend_hint = s2;
    } else {
        if (std.rand(0, 100) < 50) {
            req.backend_hint = s1;
        } else {
            req.backend_hint = s2;
        }
    }
    return (pass);
}

or in Nginx, you can define a map in http section:

map $cookie_proxy_override $my_upstream {
  default default-server-or-upstream;
  ~^(?P<name>[\w-]+) $name;
}

Then you simply use $my_upstream in location section(s):

location /original-request {
  proxy_pass http://$my_upstream$uri;
}

Nginx evaluates map variables lazily, only once (per request) and when you are using them.

server {
    ...
    set $upstream "default-server-or-upstream";
    if ($http_cookie ~ "proxy_override=([\w-]+)") {
        set $upstream $1;                                   
    }

    location /original-request {
        proxy_pass http://$upstream/original-application
    }
}

I asked Brave search AI and it gave me:

defmodule MyApp.Router do
  use Plug.Router

  plug :match
  plug :dispatch

  get "/hello" do
    case get_req_header(conn, "cookie") do
      [{"cookie_value"}] -> send_resp(conn, 200, "Cookie matched")
      _ -> send_resp(conn, 400, "Cookie not matched")
    end
  end
end

or

defmodule MyApp.Router do
  use Plug.Router

  plug :match
  plug :dispatch

  get "/set-cookie" do
    domain = PublicSuffix.registrable_domain(conn.host)
    opts = [store: :cookie, key: "_myapp_key", signing_salt: "asdadl", domain: domain, max_age: max_age, http_only: true]
    opts = Plug.Session.init(opts)
    conn = Plug.Session.call(conn, opts)
    send_resp(conn, 200, "Cookie set")
  end
end

@tangui

Most Liked

tangui

tangui

Using plug_http_cache, you can always refuse a cached version to be served by setting the request cache-control: no-cache header.

The spec states that:

The no-cache request directive indicates that the client prefers a stored response not be used to satisfy the request without successful validation on the origin server.

Luckily, plug_http_cache doesn’t support revalidation* and doesn’t return a cached version in this case, so what you have to do is just to write a Plug before plug_http_cache that

  • reads if there is a specific cookie / cookie value (user authenticated for instance)
  • set this cache-control: no-cache request header if so

Cheers

* You should have a test for this, since plug_http_cache might support revalidation in the future, although it is not very likely

EDIT: might even be better to set the request header cache-control: max-age=0

Where Next?

Popular in Questions Top

chokchit
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 2733ms. You can configure how long re...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
vac
Hi, I’m quite new in Elixir and I’m trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and I...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: &lt;h1&gt;Create Post&lt;/h1&gt; &lt;%= ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement