Returning erlang output via send_resp in Phoenix 1.7.4?

I am trying to solve a simple problem in Phoenix: I have lots of erlang code that outputs text using io:format. How can I return that to a plaintext web page through phoenix?

Let’s say for example I have this erlang code in mymodule.erl:


-module(mymodule).
-compile(export_all).

myfunc() ->
        io:format("hello~n"),
        io:format("world~n").

How can i return the output text of mymodule:myfunc() in an endpoint using phoenix?

Something like this:


defmodule ErlfuncWeb.PageController do
  use ErlfuncWeb, :controller

  def home(conn, _params) do
    # The home page is often custom made,
    # so skip the default app layout.
    render(conn, :home, layout: false)
  end

  def erlfunc(conn, _params) do
       # this next call generates a lot of text I want to return to the web page as plaintest.
        :mymodule.myfunc()
        conn
        |> put_resp_content_type("text/plain")
        |> send_resp(200, "done" )
  end
end

Additional Context: this works in iex, and the idea would be to return the following as part of the web page content returned by Phoenix:
hello
world

controllers % iex
Erlang/OTP 25 [erts-13.2.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.15.7) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :mymodule.myfunc()
hello
world
:ok
iex(2)>

Try this:

  def erlfunc(conn, _params) do
       output = :mymodule.myfunc() 

        conn
        |> put_resp_content_type("text/plain")
        |> send_resp(200, output)
  end

If you are still struggling, you will need to give us more details on what you’ve tried, where it’s failing, error messages etc…

I did try this and it works fine if the function module.myfunc() returns a value. However I want my response to include any text dumped using io:format, not just the last value returned from module.myfunc(). In other words … I need to send all output from io:output back to the web client as part of the response.

Perhaps HTML templates are the way to do that? I’m not sure.

I can use the app generated in the example for Phoenix channels to provide complete context. So my setup is exactly as defined at Channels — Phoenix v1.7.10.

Then lib/hello_web/controllers/page_controller.ex i have this:

defmodule HelloWeb.PageController do
  use HelloWeb, :controller

  def home(conn, _params) do
    fooresult = :io.format("foo result")
    
    # The home page is often custom made,
    # so skip the default app layout.
    render(conn, :home, layout: false, result: fooresult)
  end
end

And in lib/controllers/page_html/home.html.heex I have this:

<div id="messages" role="log" aria-live="polite"></div>
<input id="chat-input" type="text">

<h1>Output</h1>
<p>Passed in result: <%= @result %></p>
<p><%= :io.format("ONE") %></p>

The output I see on the screen is the input box expected in the example followed by this text:

Output
Passed in result: ok
ok

The result displayed is “ok” which is the return status from calling io.format(). What I want instead is to display the formatted text I pass into io.format. Like this:

Output
Passed in result: foo result
ONE

How can I do that?

Hope that clarifies.

Use :io_lib.format(...). :io.format() print to stdout.

O.K. I’ll try that.
Also I just now got this approach to work:

  1. compile my erlang code to .beam files and add them to a library on the server. For example I compile this and add it to /_build/dev/lib/phoenix/ebin:
-module(hello).
-compile(export_all).

world() ->
        "hello world result".
  1. I then updated the page controller to this:
defmodule HelloWeb.PageController do
  use HelloWeb, :controller

  def home(conn, _params) do
    fooresult = :hello.world()
    # :io.format("foo result")
    
    # The home page is often custom made,
    # so skip the default app layout.
    render(conn, :home, layout: false, result: fooresult)
  end
end

And that works … it gives me the expected output:

Output
Passed in result: hello world result
ok

So I I have a more complicated erlang application I can build it as a module and include the module.

I think I’m good now. Thanks for the help and suggestions.