POST/PUT/PATCH
beno opened this issue · comments
What is the best way to handle requests with payloads? I can't figure out how to access the request body and pass it on.
Related question: is it possible to basically clone an incoming request, modify some aspects (like the host and path) of it and then execute that?
Rackla is built using Plug so everything you can do in Plug, you can also do in Rackla. You can either use the Plug.Conn.read_body/2 or you can use Plug.Parsers if you want to do more complex things.
Example:
{:ok, body, conn} = Plug.Conn.read_body(conn)
It is not possible to convert an incoming "Plug request" to a "Rackla request", but that would actually be a really good feature. I will look into that!
Great, thanks, I got it working. I knew there was a way, but my Elixir-fu just isn't all that great.
To be honest, I was fully expecting that request-proxy trick to be the core feature of an API-Gateway framework like Rackla. So I am glad you are looking into it! Thanks again.
Edit: FYI, here's how I ended up solving it:
defmodule Router do
use Plug.Router
import Rackla
plug :match
plug :dispatch
defp proxy(url, conn) do
method = conn.method |> String.downcase |> String.to_atom
{:ok, body, _conn} = Plug.Conn.read_body(conn)
%Rackla.Request{url: url, method: method, body: body, headers: conn.req_headers}
|> request
|> response
end
match "/admin/*path" do
"http://admin.example.com:9292/v1/#{Enum.join(path,"/")}"
|> proxy(conn)
end
match _ do
send_resp(conn, 404, "Endpoint not found")
end
end
Nice solution!
You should always reassign conn
to the new conn
returned by the function and not do _conn
. (It will probably work anyway but this is the desired practice.)
As of version 1.1.0, you can now use the built in function incoming_request
:
get "/test/a-simple-request-proxy" do
# You should check for errors
{:ok, the_request} = incoming_request()
the_request
|> Map.put(:url, "http://new-url.com")
|> request
|> response
end
Look for the macro incoming_request
in the documentation!
O that is sweet. Thanks!
Hi, I hadn't had a chance to implement this yet, but I now have and there are two issues I'd like to report:
- When I write the code as above, I run into a compilation error
** (CompileError) lib/deal_manager.ex: invalid quoted expression: %{}
(rackla) expanding macro: Rackla.incoming_request/0
I can get around this by calling incoming_request(%{})
.
- The incoming request loses the
query_string
. Can't have that 😄
Not a real issue form me since I rewrite the url, but still.
Other than that it all seems to work, but I haven't done all my tests yet.
Thanks for the report! I'll fix these issues as soon as possible :)
Fixed in 1.2.1! (See #25)