0
votes

I've inherited a project written in Elixir. Basically it's a API gateway. In this case, I need to perform a redirect from my API Gateway URL to the one which the destination URL redirects to. So the situation is like this.

Request to (API Gateway in Elixir) > goes to my server, which returns a 302 and redirects to another URL.

I've written some code like this:

def index(%{query_string: query_string} = conn, data) do
  final_conn =
    case MyLib.index(data, [], query_string) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        conn
        |> put_status(200)
        |> put_resp_content_type("application/vnd.api+json")
        |> json(body)
      {:ok, %HTTPoison.Response{status_code: 500, body: body}} ->
        conn
        |> put_status(500)
        |> put_resp_content_type("application/vnd.api+json")
        |> json(body)
      {:ok, %HTTPoison.Response{status_code: 302, body: body}} ->
        conn
        |> put_status(302)
        |> redirect(to: conn)
        |> Plug.Conn.halt()
      {:ok, %HTTPoison.Response{status_code: 303, body: body}} ->
        conn
        |> put_status(303)
        |> redirect(to: conn)
        |> Plug.Conn.halt()
      {:ok, %HTTPoison.Response{status_code: 404}} ->
        conn
        |> put_status(404)
        |> put_resp_content_type("application/vnd.api+json")
        |> json(%{error_code: "404", reason_given: "Resource not found."})
      {:error, %HTTPoison.Error{reason: reason}} ->
        conn
        |> put_status(500)
        |> put_resp_content_type("application/vnd.api+json")
        |> json(%{error_code: "500", reason_given: reason})
    end

    final_conn

where MyLib.index is simply

def index(conn, headers \\ [], query_string) do
  HTTPoison.get(process_url("?#{query_string}"), headers)
end

This code correctly manage the error parts, but I'm not able to make it work for 301 or 302.

(It goes without saying, I've never seen Elixir in my life).

1
What is redirect(to: conn) meant to do? I am used to seeing redirect(to: "some_actual_url.xyz") - Peaceful James
I'm confused by your description, e.g. "goes to my server" -- is there more than one server? Is there one that isn't yours? Can you walk us step by step through a request and explain the desired behavior? - Everett
@PeacefulJames yes, you are right. What I'm trying to do is redirect to the url to which the proxied url is redirected. Please see also my comment below if that's not clear. - alex89x
@Everett Yes, I have 2 endpoints... The api gateway endpoint (this one in Elixir) is public, and it just acts as a proxy for another server, which is not public. This particular endpoint in the private internal server returns a 302 and redirect to a 3rd url... (I'm sorry for it but it was done this way)... So what I'm trying to accomplish here is that the Elixir server public endpoint manages to redirect the external caller to that final url... - alex89x
I think you might get what you want if you simply add set the :follow_redirect option to true in your HTTPoison.get/3 call, e.g. HTTPoison.get(process_url("?#{query_string}"), headers, follow_redirect: true). (I think HTTPoison doesn't follow redirects by default) - Everett

1 Answers

0
votes

Thanks to the comments, I've tried a different approach. The project I've inherited has a lot of specific customization for some endpoints, and in this case I didn't need any of them. Thus, the only code I needed was the following:

def index(%{query_string: query_string} = conn, data) do
    redirect(conn, external: process_url("?#{query_string}"))
end

Thank you all for the support.